Home | History | Annotate | Download | only in batterytip
      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.support.annotation.VisibleForTesting;
     29 import android.text.TextUtils;
     30 import android.util.Base64;
     31 import android.util.Log;
     32 
     33 import com.android.settings.R;
     34 import com.android.settingslib.utils.ThreadUtils;
     35 
     36 import java.util.concurrent.TimeUnit;
     37 
     38 /** A JobService check whether to update the anomaly config periodically */
     39 public class AnomalyConfigJobService extends JobService {
     40     private static final String TAG = "AnomalyConfigJobService";
     41 
     42     public static final String PREF_DB = "anomaly_pref";
     43     public static final String KEY_ANOMALY_CONFIG_VERSION = "anomaly_config_version";
     44     private static final int DEFAULT_VERSION = 0;
     45 
     46     @VisibleForTesting
     47     static final long CONFIG_UPDATE_FREQUENCY_MS = TimeUnit.DAYS.toMillis(1);
     48 
     49     public static void scheduleConfigUpdate(Context context) {
     50         final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
     51 
     52         final ComponentName component = new ComponentName(context, AnomalyConfigJobService.class);
     53         final JobInfo.Builder jobBuilder =
     54                 new JobInfo.Builder(R.integer.job_anomaly_config_update, component)
     55                         .setPeriodic(CONFIG_UPDATE_FREQUENCY_MS)
     56                         .setRequiresDeviceIdle(true)
     57                         .setRequiresCharging(true)
     58                         .setPersisted(true);
     59         final JobInfo pending = jobScheduler.getPendingJob(R.integer.job_anomaly_config_update);
     60 
     61         // Don't schedule it if it already exists, to make sure it runs periodically even after
     62         // reboot
     63         if (pending == null && jobScheduler.schedule(jobBuilder.build())
     64                 != JobScheduler.RESULT_SUCCESS) {
     65             Log.i(TAG, "Anomaly config update job service schedule failed.");
     66         }
     67     }
     68 
     69     @Override
     70     public boolean onStartJob(JobParameters params) {
     71         ThreadUtils.postOnBackgroundThread(() -> {
     72             final StatsManager statsManager = getSystemService(StatsManager.class);
     73             checkAnomalyConfig(statsManager);
     74             try {
     75                 BatteryTipUtils.uploadAnomalyPendingIntent(this, statsManager);
     76             } catch (StatsManager.StatsUnavailableException e) {
     77                 Log.w(TAG, "Failed to uploadAnomalyPendingIntent.", e);
     78             }
     79             jobFinished(params, false /* wantsReschedule */);
     80         });
     81 
     82         return true;
     83     }
     84 
     85     @Override
     86     public boolean onStopJob(JobParameters jobParameters) {
     87         return false;
     88     }
     89 
     90     @VisibleForTesting
     91     synchronized void checkAnomalyConfig(StatsManager statsManager) {
     92         final SharedPreferences sharedPreferences = getSharedPreferences(PREF_DB,
     93                 Context.MODE_PRIVATE);
     94         final int currentVersion = sharedPreferences.getInt(KEY_ANOMALY_CONFIG_VERSION,
     95                 DEFAULT_VERSION);
     96         final int newVersion = Settings.Global.getInt(getContentResolver(),
     97                 Settings.Global.ANOMALY_CONFIG_VERSION, DEFAULT_VERSION);
     98         final String rawConfig = Settings.Global.getString(getContentResolver(),
     99                 Settings.Global.ANOMALY_CONFIG);
    100         Log.i(TAG, "CurrentVersion: " + currentVersion + " new version: " + newVersion);
    101 
    102         if (newVersion > currentVersion) {
    103             try {
    104                 statsManager.removeConfig(StatsManagerConfig.ANOMALY_CONFIG_KEY);
    105             } catch (StatsManager.StatsUnavailableException e) {
    106                 Log.i(TAG, "When updating anomaly config, failed to first remove the old config "
    107                         + StatsManagerConfig.ANOMALY_CONFIG_KEY, e);
    108             }
    109             if (!TextUtils.isEmpty(rawConfig)) {
    110                 try {
    111                     final byte[] config = Base64.decode(rawConfig, Base64.DEFAULT);
    112                     statsManager.addConfig(StatsManagerConfig.ANOMALY_CONFIG_KEY, config);
    113                     Log.i(TAG, "Upload the anomaly config. configKey: "
    114                             + StatsManagerConfig.ANOMALY_CONFIG_KEY);
    115                     SharedPreferences.Editor editor = sharedPreferences.edit();
    116                     editor.putInt(KEY_ANOMALY_CONFIG_VERSION, newVersion);
    117                     editor.commit();
    118                 } catch (IllegalArgumentException e) {
    119                     Log.e(TAG, "Anomaly raw config is in wrong format", e);
    120                 } catch (StatsManager.StatsUnavailableException e) {
    121                     Log.i(TAG, "Upload of anomaly config failed for configKey "
    122                             + StatsManagerConfig.ANOMALY_CONFIG_KEY, e);
    123                 }
    124             }
    125         }
    126     }
    127 }
    128