Home | History | Annotate | Download | only in checker
      1 /*
      2  * Copyright (C) 2017 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.anomaly.checker;
     18 
     19 import android.content.Context;
     20 import android.content.pm.PackageManager;
     21 import android.os.BatteryStats;
     22 import android.os.SystemClock;
     23 import android.support.annotation.VisibleForTesting;
     24 
     25 import com.android.internal.os.BatterySipper;
     26 import com.android.internal.os.BatteryStatsHelper;
     27 import com.android.settings.Utils;
     28 import com.android.settings.fuelgauge.BatteryUtils;
     29 import com.android.settings.fuelgauge.anomaly.Anomaly;
     30 import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy;
     31 import com.android.settings.fuelgauge.anomaly.AnomalyUtils;
     32 
     33 import java.util.ArrayList;
     34 import java.util.List;
     35 
     36 /**
     37  * Check whether apps holding wakelock too long
     38  */
     39 public class WakeLockAnomalyDetector implements AnomalyDetector {
     40     private static final String TAG = "WakeLockAnomalyChecker";
     41     @VisibleForTesting
     42     BatteryUtils mBatteryUtils;
     43     @VisibleForTesting
     44     long mWakeLockThresholdMs;
     45     private PackageManager mPackageManager;
     46     private Context mContext;
     47     private AnomalyUtils mAnomalyUtils;
     48 
     49     public WakeLockAnomalyDetector(Context context) {
     50         this(context, new AnomalyDetectionPolicy(context), AnomalyUtils.getInstance(context));
     51     }
     52 
     53     @VisibleForTesting
     54     WakeLockAnomalyDetector(Context context, AnomalyDetectionPolicy policy,
     55             AnomalyUtils anomalyUtils) {
     56         mContext = context;
     57         mPackageManager = context.getPackageManager();
     58         mBatteryUtils = BatteryUtils.getInstance(context);
     59         mAnomalyUtils = anomalyUtils;
     60         mWakeLockThresholdMs = policy.wakeLockThreshold;
     61     }
     62 
     63     @Override
     64     public List<Anomaly> detectAnomalies(BatteryStatsHelper batteryStatsHelper) {
     65         // Detect all apps if targetPackageName is null
     66         return detectAnomalies(batteryStatsHelper, null /* targetPackageName */);
     67     }
     68 
     69     @Override
     70     public List<Anomaly> detectAnomalies(BatteryStatsHelper batteryStatsHelper,
     71             String targetPackageName) {
     72         final List<BatterySipper> batterySippers = batteryStatsHelper.getUsageList();
     73         final List<Anomaly> anomalies = new ArrayList<>();
     74         final long rawRealtime = SystemClock.elapsedRealtime();
     75         final int targetUid = mBatteryUtils.getPackageUid(targetPackageName);
     76 
     77         // Check the app one by one
     78         for (int i = 0, size = batterySippers.size(); i < size; i++) {
     79             final BatterySipper sipper = batterySippers.get(i);
     80             final BatteryStats.Uid uid = sipper.uidObj;
     81             if (uid == null
     82                     || mBatteryUtils.shouldHideSipper(sipper)
     83                     || (targetUid != BatteryUtils.UID_NULL && targetUid != uid.getUid())) {
     84                 continue;
     85             }
     86 
     87             final long currentDurationMs = getCurrentDurationMs(uid, rawRealtime);
     88             final long backgroundDurationMs = getBackgroundTotalDurationMs(uid, rawRealtime);
     89 
     90             if (backgroundDurationMs > mWakeLockThresholdMs && currentDurationMs != 0) {
     91                 final String packageName = mBatteryUtils.getPackageName(uid.getUid());
     92                 final CharSequence displayName = Utils.getApplicationLabel(mContext,
     93                         packageName);
     94 
     95                 Anomaly anomaly = new Anomaly.Builder()
     96                         .setUid(uid.getUid())
     97                         .setType(Anomaly.AnomalyType.WAKE_LOCK)
     98                         .setDisplayName(displayName)
     99                         .setPackageName(packageName)
    100                         .setWakeLockTimeMs(backgroundDurationMs)
    101                         .build();
    102 
    103                 if (mAnomalyUtils.getAnomalyAction(anomaly).isActionActive(anomaly)) {
    104                     anomalies.add(anomaly);
    105                 }
    106             }
    107         }
    108         return anomalies;
    109     }
    110 
    111     @VisibleForTesting
    112     long getCurrentDurationMs(BatteryStats.Uid uid, long elapsedRealtimeMs) {
    113         BatteryStats.Timer timer = uid.getAggregatedPartialWakelockTimer();
    114 
    115         return timer != null ? timer.getCurrentDurationMsLocked(elapsedRealtimeMs) : 0;
    116     }
    117 
    118     @VisibleForTesting
    119     long getBackgroundTotalDurationMs(BatteryStats.Uid uid, long elapsedRealtimeMs) {
    120         BatteryStats.Timer timer = uid.getAggregatedPartialWakelockTimer();
    121         BatteryStats.Timer subTimer = timer != null ? timer.getSubTimer() : null;
    122 
    123         return subTimer != null ? subTimer.getTotalDurationMsLocked(elapsedRealtimeMs) : 0;
    124     }
    125 }
    126