Loading AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -3258,6 +3258,9 @@ <service android:name=".fuelgauge.batterytip.AnomalyCleanupJobService" android:permission="android.permission.BIND_JOB_SERVICE" /> <service android:name=".fuelgauge.batterytip.AnomalyConfigJobService" android:permission="android.permission.BIND_JOB_SERVICE" /> <service android:name=".fuelgauge.batterytip.AnomalyDetectionJobService" android:permission="android.permission.BIND_JOB_SERVICE" /> Loading res/values/ids.xml +1 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ <resources> <item type="id" name="preference_highlighted" /> <item type="id" name="job_anomaly_clean_up" /> <item type="id" name="job_anomaly_config_update"/> <item type="id" name="job_anomaly_detection" /> <item type="id" name="lock_none" /> Loading src/com/android/settings/fuelgauge/batterytip/AnomalyCleanupJobService.java +1 −2 Original line number Diff line number Diff line Loading @@ -45,8 +45,7 @@ public class AnomalyCleanupJobService extends JobService { new JobInfo.Builder(R.id.job_anomaly_clean_up, component) .setPeriodic(CLEAN_UP_FREQUENCY_MS) .setRequiresDeviceIdle(true) .setRequiresCharging(true) .setPersisted(true); .setRequiresCharging(true); if (jobScheduler.schedule(jobBuilder.build()) != JobScheduler.RESULT_SUCCESS) { Log.i(TAG, "Anomaly clean up job service schedule failed."); Loading src/com/android/settings/fuelgauge/batterytip/AnomalyConfigJobService.java 0 → 100644 +116 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.fuelgauge.batterytip; import android.app.StatsManager; import android.app.job.JobInfo; import android.app.job.JobParameters; import android.app.job.JobScheduler; import android.app.job.JobService; import android.content.ComponentName; import android.content.Context; import android.content.SharedPreferences; import android.provider.Settings; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.util.Base64; import android.util.Log; import com.android.settings.R; import com.android.settingslib.utils.ThreadUtils; import java.util.concurrent.TimeUnit; /** A JobService check whether to update the anomaly config periodically */ public class AnomalyConfigJobService extends JobService { private static final String TAG = "AnomalyConfigJobService"; @VisibleForTesting static final String PREF_DB = "anomaly_pref"; private static final String KEY_ANOMALY_CONFIG_VERSION = "anomaly_config_version"; private static final int DEFAULT_VERSION = 0; @VisibleForTesting static final long CONFIG_UPDATE_FREQUENCY_MS = TimeUnit.DAYS.toMillis(1); public static void scheduleConfigUpdate(Context context) { final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); final ComponentName component = new ComponentName(context, AnomalyConfigJobService.class); final JobInfo.Builder jobBuilder = new JobInfo.Builder(R.id.job_anomaly_config_update, component) .setPeriodic(CONFIG_UPDATE_FREQUENCY_MS) .setRequiresDeviceIdle(true) .setRequiresCharging(true); if (jobScheduler.schedule(jobBuilder.build()) != JobScheduler.RESULT_SUCCESS) { Log.i(TAG, "Anomaly config update job service schedule failed."); } } @Override public boolean onStartJob(JobParameters params) { ThreadUtils.postOnBackgroundThread(() -> { final StatsManager statsManager = getSystemService(StatsManager.class); checkAnomalyConfig(statsManager); BatteryTipUtils.uploadAnomalyPendingIntent(this, statsManager); jobFinished(params, false /* wantsReschedule */); }); return true; } @Override public boolean onStopJob(JobParameters jobParameters) { return false; } @VisibleForTesting synchronized void checkAnomalyConfig(StatsManager statsManager) { final SharedPreferences sharedPreferences = getSharedPreferences(PREF_DB, Context.MODE_PRIVATE); final int currentVersion = sharedPreferences.getInt(KEY_ANOMALY_CONFIG_VERSION, DEFAULT_VERSION); final int newVersion = Settings.Global.getInt(getContentResolver(), Settings.Global.ANOMALY_CONFIG_VERSION, DEFAULT_VERSION); final String rawConfig = Settings.Global.getString(getContentResolver(), Settings.Global.ANOMALY_CONFIG); Log.i(TAG, "CurrentVersion: " + currentVersion + " new version: " + newVersion); if (newVersion > currentVersion) { statsManager.removeConfiguration(StatsManagerConfig.ANOMALY_CONFIG_KEY); if (!TextUtils.isEmpty(rawConfig)) { try { final byte[] config = Base64.decode(rawConfig, Base64.DEFAULT); if (statsManager.addConfiguration(StatsManagerConfig.ANOMALY_CONFIG_KEY, config)) { Log.i(TAG, "Upload the anomaly config. configKey: " + StatsManagerConfig.ANOMALY_CONFIG_KEY); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putInt(KEY_ANOMALY_CONFIG_VERSION, newVersion); editor.commit(); } else { Log.i(TAG, "Upload the anomaly config failed. configKey: " + StatsManagerConfig.ANOMALY_CONFIG_KEY); } } catch (IllegalArgumentException e) { Log.e(TAG, "Anomaly raw config is in wrong format", e); } } } } } src/com/android/settings/fuelgauge/batterytip/AnomalyConfigReceiver.java +2 −40 Original line number Diff line number Diff line Loading @@ -21,9 +21,6 @@ import android.app.StatsManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.provider.Settings; import android.util.Base64; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; Loading @@ -34,10 +31,6 @@ import com.android.internal.annotations.VisibleForTesting; */ public class AnomalyConfigReceiver extends BroadcastReceiver { private static final String TAG = "AnomalyConfigReceiver"; private static final int REQUEST_CODE = 0; private static final String PREF_DB = "anomaly_pref"; private static final String KEY_ANOMALY_CONFIG_VERSION = "anomaly_config_version"; private static final int DEFAULT_VERSION = 0; @Override public void onReceive(Context context, Intent intent) { Loading @@ -46,14 +39,9 @@ public class AnomalyConfigReceiver extends BroadcastReceiver { final StatsManager statsManager = context.getSystemService(StatsManager.class); // Check whether to update the config checkAnomalyConfig(context, statsManager); AnomalyConfigJobService.scheduleConfigUpdate(context); // Upload PendingIntent to StatsManager final Intent extraIntent = new Intent(context, AnomalyDetectionReceiver.class); final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, extraIntent, PendingIntent.FLAG_UPDATE_CURRENT); uploadPendingIntent(statsManager, pendingIntent); BatteryTipUtils.uploadAnomalyPendingIntent(context, statsManager); if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { AnomalyCleanupJobService.scheduleCleanUp(context); Loading @@ -69,30 +57,4 @@ public class AnomalyConfigReceiver extends BroadcastReceiver { statsManager.setBroadcastSubscriber(StatsManagerConfig.ANOMALY_CONFIG_KEY, StatsManagerConfig.SUBSCRIBER_ID, pendingIntent); } private void checkAnomalyConfig(Context context, StatsManager statsManager) { final SharedPreferences sharedPreferences = context.getSharedPreferences(PREF_DB, Context.MODE_PRIVATE); final int currentVersion = sharedPreferences.getInt(KEY_ANOMALY_CONFIG_VERSION, DEFAULT_VERSION); final int newVersion = Settings.Global.getInt(context.getContentResolver(), Settings.Global.ANOMALY_CONFIG_VERSION, DEFAULT_VERSION); Log.i(TAG, "CurrentVersion: " + currentVersion + " new version: " + newVersion); if (newVersion > currentVersion) { final byte[] config = Base64.decode( Settings.Global.getString(context.getContentResolver(), Settings.Global.ANOMALY_CONFIG), Base64.DEFAULT); if (statsManager.addConfiguration(StatsManagerConfig.ANOMALY_CONFIG_KEY, config)) { Log.i(TAG, "Upload the anomaly config. configKey: " + StatsManagerConfig.ANOMALY_CONFIG_KEY); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putInt(KEY_ANOMALY_CONFIG_VERSION, newVersion); editor.apply(); } else { Log.i(TAG, "Upload the anomaly config failed. configKey: " + StatsManagerConfig.ANOMALY_CONFIG_KEY); } } } } Loading
AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -3258,6 +3258,9 @@ <service android:name=".fuelgauge.batterytip.AnomalyCleanupJobService" android:permission="android.permission.BIND_JOB_SERVICE" /> <service android:name=".fuelgauge.batterytip.AnomalyConfigJobService" android:permission="android.permission.BIND_JOB_SERVICE" /> <service android:name=".fuelgauge.batterytip.AnomalyDetectionJobService" android:permission="android.permission.BIND_JOB_SERVICE" /> Loading
res/values/ids.xml +1 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ <resources> <item type="id" name="preference_highlighted" /> <item type="id" name="job_anomaly_clean_up" /> <item type="id" name="job_anomaly_config_update"/> <item type="id" name="job_anomaly_detection" /> <item type="id" name="lock_none" /> Loading
src/com/android/settings/fuelgauge/batterytip/AnomalyCleanupJobService.java +1 −2 Original line number Diff line number Diff line Loading @@ -45,8 +45,7 @@ public class AnomalyCleanupJobService extends JobService { new JobInfo.Builder(R.id.job_anomaly_clean_up, component) .setPeriodic(CLEAN_UP_FREQUENCY_MS) .setRequiresDeviceIdle(true) .setRequiresCharging(true) .setPersisted(true); .setRequiresCharging(true); if (jobScheduler.schedule(jobBuilder.build()) != JobScheduler.RESULT_SUCCESS) { Log.i(TAG, "Anomaly clean up job service schedule failed."); Loading
src/com/android/settings/fuelgauge/batterytip/AnomalyConfigJobService.java 0 → 100644 +116 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.fuelgauge.batterytip; import android.app.StatsManager; import android.app.job.JobInfo; import android.app.job.JobParameters; import android.app.job.JobScheduler; import android.app.job.JobService; import android.content.ComponentName; import android.content.Context; import android.content.SharedPreferences; import android.provider.Settings; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.util.Base64; import android.util.Log; import com.android.settings.R; import com.android.settingslib.utils.ThreadUtils; import java.util.concurrent.TimeUnit; /** A JobService check whether to update the anomaly config periodically */ public class AnomalyConfigJobService extends JobService { private static final String TAG = "AnomalyConfigJobService"; @VisibleForTesting static final String PREF_DB = "anomaly_pref"; private static final String KEY_ANOMALY_CONFIG_VERSION = "anomaly_config_version"; private static final int DEFAULT_VERSION = 0; @VisibleForTesting static final long CONFIG_UPDATE_FREQUENCY_MS = TimeUnit.DAYS.toMillis(1); public static void scheduleConfigUpdate(Context context) { final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); final ComponentName component = new ComponentName(context, AnomalyConfigJobService.class); final JobInfo.Builder jobBuilder = new JobInfo.Builder(R.id.job_anomaly_config_update, component) .setPeriodic(CONFIG_UPDATE_FREQUENCY_MS) .setRequiresDeviceIdle(true) .setRequiresCharging(true); if (jobScheduler.schedule(jobBuilder.build()) != JobScheduler.RESULT_SUCCESS) { Log.i(TAG, "Anomaly config update job service schedule failed."); } } @Override public boolean onStartJob(JobParameters params) { ThreadUtils.postOnBackgroundThread(() -> { final StatsManager statsManager = getSystemService(StatsManager.class); checkAnomalyConfig(statsManager); BatteryTipUtils.uploadAnomalyPendingIntent(this, statsManager); jobFinished(params, false /* wantsReschedule */); }); return true; } @Override public boolean onStopJob(JobParameters jobParameters) { return false; } @VisibleForTesting synchronized void checkAnomalyConfig(StatsManager statsManager) { final SharedPreferences sharedPreferences = getSharedPreferences(PREF_DB, Context.MODE_PRIVATE); final int currentVersion = sharedPreferences.getInt(KEY_ANOMALY_CONFIG_VERSION, DEFAULT_VERSION); final int newVersion = Settings.Global.getInt(getContentResolver(), Settings.Global.ANOMALY_CONFIG_VERSION, DEFAULT_VERSION); final String rawConfig = Settings.Global.getString(getContentResolver(), Settings.Global.ANOMALY_CONFIG); Log.i(TAG, "CurrentVersion: " + currentVersion + " new version: " + newVersion); if (newVersion > currentVersion) { statsManager.removeConfiguration(StatsManagerConfig.ANOMALY_CONFIG_KEY); if (!TextUtils.isEmpty(rawConfig)) { try { final byte[] config = Base64.decode(rawConfig, Base64.DEFAULT); if (statsManager.addConfiguration(StatsManagerConfig.ANOMALY_CONFIG_KEY, config)) { Log.i(TAG, "Upload the anomaly config. configKey: " + StatsManagerConfig.ANOMALY_CONFIG_KEY); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putInt(KEY_ANOMALY_CONFIG_VERSION, newVersion); editor.commit(); } else { Log.i(TAG, "Upload the anomaly config failed. configKey: " + StatsManagerConfig.ANOMALY_CONFIG_KEY); } } catch (IllegalArgumentException e) { Log.e(TAG, "Anomaly raw config is in wrong format", e); } } } } }
src/com/android/settings/fuelgauge/batterytip/AnomalyConfigReceiver.java +2 −40 Original line number Diff line number Diff line Loading @@ -21,9 +21,6 @@ import android.app.StatsManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.provider.Settings; import android.util.Base64; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; Loading @@ -34,10 +31,6 @@ import com.android.internal.annotations.VisibleForTesting; */ public class AnomalyConfigReceiver extends BroadcastReceiver { private static final String TAG = "AnomalyConfigReceiver"; private static final int REQUEST_CODE = 0; private static final String PREF_DB = "anomaly_pref"; private static final String KEY_ANOMALY_CONFIG_VERSION = "anomaly_config_version"; private static final int DEFAULT_VERSION = 0; @Override public void onReceive(Context context, Intent intent) { Loading @@ -46,14 +39,9 @@ public class AnomalyConfigReceiver extends BroadcastReceiver { final StatsManager statsManager = context.getSystemService(StatsManager.class); // Check whether to update the config checkAnomalyConfig(context, statsManager); AnomalyConfigJobService.scheduleConfigUpdate(context); // Upload PendingIntent to StatsManager final Intent extraIntent = new Intent(context, AnomalyDetectionReceiver.class); final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, extraIntent, PendingIntent.FLAG_UPDATE_CURRENT); uploadPendingIntent(statsManager, pendingIntent); BatteryTipUtils.uploadAnomalyPendingIntent(context, statsManager); if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { AnomalyCleanupJobService.scheduleCleanUp(context); Loading @@ -69,30 +57,4 @@ public class AnomalyConfigReceiver extends BroadcastReceiver { statsManager.setBroadcastSubscriber(StatsManagerConfig.ANOMALY_CONFIG_KEY, StatsManagerConfig.SUBSCRIBER_ID, pendingIntent); } private void checkAnomalyConfig(Context context, StatsManager statsManager) { final SharedPreferences sharedPreferences = context.getSharedPreferences(PREF_DB, Context.MODE_PRIVATE); final int currentVersion = sharedPreferences.getInt(KEY_ANOMALY_CONFIG_VERSION, DEFAULT_VERSION); final int newVersion = Settings.Global.getInt(context.getContentResolver(), Settings.Global.ANOMALY_CONFIG_VERSION, DEFAULT_VERSION); Log.i(TAG, "CurrentVersion: " + currentVersion + " new version: " + newVersion); if (newVersion > currentVersion) { final byte[] config = Base64.decode( Settings.Global.getString(context.getContentResolver(), Settings.Global.ANOMALY_CONFIG), Base64.DEFAULT); if (statsManager.addConfiguration(StatsManagerConfig.ANOMALY_CONFIG_KEY, config)) { Log.i(TAG, "Upload the anomaly config. configKey: " + StatsManagerConfig.ANOMALY_CONFIG_KEY); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putInt(KEY_ANOMALY_CONFIG_VERSION, newVersion); editor.apply(); } else { Log.i(TAG, "Upload the anomaly config failed. configKey: " + StatsManagerConfig.ANOMALY_CONFIG_KEY); } } } }