• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.fuelgauge.batterytip;
18 
19 import android.app.StatsManager;
20 import android.app.job.JobInfo;
21 import android.app.job.JobParameters;
22 import android.app.job.JobScheduler;
23 import android.app.job.JobService;
24 import android.content.ComponentName;
25 import android.content.Context;
26 import android.content.SharedPreferences;
27 import android.provider.Settings;
28 import android.text.TextUtils;
29 import android.util.Base64;
30 import android.util.Log;
31 
32 import androidx.annotation.VisibleForTesting;
33 
34 import com.android.settings.R;
35 import com.android.settingslib.utils.ThreadUtils;
36 
37 import java.util.concurrent.TimeUnit;
38 
39 /** A JobService check whether to update the anomaly config periodically */
40 public class AnomalyConfigJobService extends JobService {
41     private static final String TAG = "AnomalyConfigJobService";
42 
43     public static final String PREF_DB = "anomaly_pref";
44     public static final String KEY_ANOMALY_CONFIG_VERSION = "anomaly_config_version";
45     private static final int DEFAULT_VERSION = 0;
46 
47     @VisibleForTesting
48     static final long CONFIG_UPDATE_FREQUENCY_MS = TimeUnit.DAYS.toMillis(1);
49 
scheduleConfigUpdate(Context context)50     public static void scheduleConfigUpdate(Context context) {
51         final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
52 
53         final ComponentName component = new ComponentName(context, AnomalyConfigJobService.class);
54         final JobInfo.Builder jobBuilder =
55                 new JobInfo.Builder(R.integer.job_anomaly_config_update, component)
56                         .setPeriodic(CONFIG_UPDATE_FREQUENCY_MS)
57                         .setRequiresDeviceIdle(true)
58                         .setRequiresCharging(true)
59                         .setPersisted(true);
60         final JobInfo pending = jobScheduler.getPendingJob(R.integer.job_anomaly_config_update);
61 
62         // Don't schedule it if it already exists, to make sure it runs periodically even after
63         // reboot
64         if (pending == null && jobScheduler.schedule(jobBuilder.build())
65                 != JobScheduler.RESULT_SUCCESS) {
66             Log.i(TAG, "Anomaly config update job service schedule failed.");
67         }
68     }
69 
70     @Override
onStartJob(JobParameters params)71     public boolean onStartJob(JobParameters params) {
72         ThreadUtils.postOnBackgroundThread(() -> {
73             final StatsManager statsManager = getSystemService(StatsManager.class);
74             checkAnomalyConfig(statsManager);
75             try {
76                 BatteryTipUtils.uploadAnomalyPendingIntent(this, statsManager);
77             } catch (StatsManager.StatsUnavailableException e) {
78                 Log.w(TAG, "Failed to uploadAnomalyPendingIntent.", e);
79             }
80             jobFinished(params, false /* wantsReschedule */);
81         });
82 
83         return true;
84     }
85 
86     @Override
onStopJob(JobParameters jobParameters)87     public boolean onStopJob(JobParameters jobParameters) {
88         return false;
89     }
90 
91     @VisibleForTesting
checkAnomalyConfig(StatsManager statsManager)92     synchronized void checkAnomalyConfig(StatsManager statsManager) {
93         final SharedPreferences sharedPreferences = getSharedPreferences(PREF_DB,
94                 Context.MODE_PRIVATE);
95         final int currentVersion = sharedPreferences.getInt(KEY_ANOMALY_CONFIG_VERSION,
96                 DEFAULT_VERSION);
97         final int newVersion = Settings.Global.getInt(getContentResolver(),
98                 Settings.Global.ANOMALY_CONFIG_VERSION, DEFAULT_VERSION);
99         final String rawConfig = Settings.Global.getString(getContentResolver(),
100                 Settings.Global.ANOMALY_CONFIG);
101         Log.i(TAG, "CurrentVersion: " + currentVersion + " new version: " + newVersion);
102 
103         if (newVersion > currentVersion) {
104             try {
105                 statsManager.removeConfig(StatsManagerConfig.ANOMALY_CONFIG_KEY);
106             } catch (StatsManager.StatsUnavailableException e) {
107                 Log.i(TAG, "When updating anomaly config, failed to first remove the old config "
108                         + StatsManagerConfig.ANOMALY_CONFIG_KEY, e);
109             }
110             if (!TextUtils.isEmpty(rawConfig)) {
111                 try {
112                     final byte[] config = Base64.decode(rawConfig, Base64.DEFAULT);
113                     statsManager.addConfig(StatsManagerConfig.ANOMALY_CONFIG_KEY, config);
114                     Log.i(TAG, "Upload the anomaly config. configKey: "
115                             + StatsManagerConfig.ANOMALY_CONFIG_KEY);
116                     SharedPreferences.Editor editor = sharedPreferences.edit();
117                     editor.putInt(KEY_ANOMALY_CONFIG_VERSION, newVersion);
118                     editor.commit();
119                 } catch (IllegalArgumentException e) {
120                     Log.e(TAG, "Anomaly raw config is in wrong format", e);
121                 } catch (StatsManager.StatsUnavailableException e) {
122                     Log.i(TAG, "Upload of anomaly config failed for configKey "
123                             + StatsManagerConfig.ANOMALY_CONFIG_KEY, e);
124                 }
125             }
126         }
127     }
128 }
129