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 static com.google.common.truth.Truth.assertThat;
     20 
     21 import static org.mockito.ArgumentMatchers.nullable;
     22 import static org.mockito.Matchers.any;
     23 import static org.mockito.Matchers.anyInt;
     24 import static org.mockito.Mockito.doReturn;
     25 import static org.mockito.Mockito.spy;
     26 
     27 import android.content.Context;
     28 import android.content.pm.ApplicationInfo;
     29 import android.os.BatteryStats;
     30 import android.os.Build;
     31 import android.text.format.DateUtils;
     32 import android.util.ArrayMap;
     33 import android.util.ArraySet;
     34 
     35 import com.android.internal.os.BatterySipper;
     36 import com.android.internal.os.BatteryStatsHelper;
     37 import com.android.settings.fuelgauge.anomaly.AnomalyUtils;
     38 import com.android.settings.testutils.SettingsRobolectricTestRunner;
     39 import com.android.settings.TestConfig;
     40 import com.android.settings.fuelgauge.BatteryUtils;
     41 import com.android.settings.fuelgauge.anomaly.Anomaly;
     42 import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy;
     43 import com.android.settings.fuelgauge.anomaly.action.AnomalyAction;
     44 
     45 import org.junit.Before;
     46 import org.junit.Test;
     47 import org.junit.runner.RunWith;
     48 import org.mockito.Mock;
     49 import org.mockito.MockitoAnnotations;
     50 import org.robolectric.RuntimeEnvironment;
     51 import org.robolectric.annotation.Config;
     52 import org.robolectric.util.ReflectionHelpers;
     53 
     54 import java.util.ArrayList;
     55 import java.util.List;
     56 import java.util.Set;
     57 
     58 @RunWith(SettingsRobolectricTestRunner.class)
     59 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
     60 public class WakeupAlarmAnomalyDetectorTest {
     61     private static final String TARGET_PACKAGE_NAME = "com.android.target";
     62     private static final String ANOMALY_PACKAGE_NAME = "com.android.anomaly";
     63     private static final boolean TARGET_BACKGROUND_RESTRICTION_ON = false;
     64     private static final boolean ANOMALY_BACKGROUND_RESTRICTION_ON = true;
     65     private static final int TARGET_SDK = Build.VERSION_CODES.L;
     66     private static final int ANOMALY_SDK = Build.VERSION_CODES.O;
     67     private static final int ANOMALY_UID = 111;
     68     private static final int NORMAL_UID = 222;
     69     private static final int TARGET_UID = 333;
     70     private static final long RUNNING_TIME_MS =
     71             1 * DateUtils.HOUR_IN_MILLIS + 10 * DateUtils.MINUTE_IN_MILLIS;
     72     private static final int ANOMALY_WAKEUP_COUNT = 500;
     73     private static final int NORMAL_WAKEUP_COUNT = 61;
     74     private static final int BLACKLISTED_WAKEUP_COUNT = 37;
     75     private static final int ANOMALY_WAKEUP_FREQUENCY = 428; // count per hour
     76     @Mock
     77     private BatteryStatsHelper mBatteryStatsHelper;
     78     @Mock
     79     private BatterySipper mAnomalySipper;
     80     @Mock
     81     private BatterySipper mNormalSipper;
     82     @Mock
     83     private BatterySipper mTargetSipper;
     84     @Mock
     85     private BatteryStats.Uid mAnomalyUid;
     86     @Mock
     87     private BatteryStats.Uid mNormalUid;
     88     @Mock
     89     private BatteryStats.Uid mTargetUid;
     90     @Mock
     91     private BatteryUtils mBatteryUtils;
     92     @Mock
     93     private BatteryStats.Uid.Pkg mPkg;
     94     @Mock
     95     private BatteryStats.Counter mCounter;
     96     @Mock
     97     private BatteryStats.Counter mCounter2;
     98     @Mock
     99     private AnomalyDetectionPolicy mPolicy;
    100     @Mock
    101     private AnomalyAction mAnomalyAction;
    102     @Mock
    103     private AnomalyUtils mAnomalyUtils;
    104 
    105     private WakeupAlarmAnomalyDetector mWakeupAlarmAnomalyDetector;
    106     private Context mContext;
    107     private List<BatterySipper> mUsageList;
    108     private Anomaly mAnomaly;
    109     private Anomaly mTargetAnomaly;
    110 
    111     @Before
    112     public void setUp() throws Exception {
    113         MockitoAnnotations.initMocks(this);
    114 
    115         mContext = spy(RuntimeEnvironment.application);
    116         ReflectionHelpers.setField(mPolicy, "wakeupAlarmThreshold", 60);
    117         final Set<String> blacklistedTags = new ArraySet<>();
    118         blacklistedTags.add("blacklistedTag");
    119         ReflectionHelpers.setField(mPolicy, "wakeupBlacklistedTags", blacklistedTags);
    120 
    121         doReturn(false).when(mBatteryUtils).shouldHideSipper(any());
    122         doReturn(RUNNING_TIME_MS).when(mBatteryUtils).calculateRunningTimeBasedOnStatsType(any(),
    123                 anyInt());
    124         doReturn(true).when(mAnomalyAction).isActionActive(any());
    125         doReturn(mAnomalyAction).when(mAnomalyUtils).getAnomalyAction(any());
    126 
    127         mAnomalySipper.uidObj = mAnomalyUid;
    128         doReturn(ANOMALY_UID).when(mAnomalyUid).getUid();
    129         mNormalSipper.uidObj = mNormalUid;
    130         doReturn(NORMAL_UID).when(mNormalUid).getUid();
    131         mTargetSipper.uidObj = mTargetUid;
    132         doReturn(TARGET_UID).when(mTargetUid).getUid();
    133 
    134         mUsageList = new ArrayList<>();
    135         mUsageList.add(mAnomalySipper);
    136         mUsageList.add(mNormalSipper);
    137         mUsageList.add(mTargetSipper);
    138         doReturn(mUsageList).when(mBatteryStatsHelper).getUsageList();
    139 
    140         doReturn(TARGET_PACKAGE_NAME).when(mBatteryUtils).getPackageName(TARGET_UID);
    141         doReturn(ANOMALY_PACKAGE_NAME).when(mBatteryUtils).getPackageName(ANOMALY_UID);
    142         doReturn(TARGET_SDK).when(mBatteryUtils).getTargetSdkVersion(TARGET_PACKAGE_NAME);
    143         doReturn(ANOMALY_SDK).when(mBatteryUtils).getTargetSdkVersion(ANOMALY_PACKAGE_NAME);
    144         doReturn(TARGET_BACKGROUND_RESTRICTION_ON).when(mBatteryUtils)
    145                 .isBackgroundRestrictionEnabled(TARGET_SDK, TARGET_UID, TARGET_PACKAGE_NAME);
    146         doReturn(ANOMALY_BACKGROUND_RESTRICTION_ON).when(mBatteryUtils)
    147                 .isBackgroundRestrictionEnabled(ANOMALY_SDK, ANOMALY_UID, ANOMALY_PACKAGE_NAME);
    148 
    149         mAnomaly = new Anomaly.Builder()
    150                 .setUid(ANOMALY_UID)
    151                 .setPackageName(ANOMALY_PACKAGE_NAME)
    152                 .setType(Anomaly.AnomalyType.WAKEUP_ALARM)
    153                 .setTargetSdkVersion(ANOMALY_SDK)
    154                 .setBackgroundRestrictionEnabled(ANOMALY_BACKGROUND_RESTRICTION_ON)
    155                 .setWakeupAlarmCount(ANOMALY_WAKEUP_FREQUENCY)
    156                 .build();
    157         mTargetAnomaly = new Anomaly.Builder()
    158                 .setUid(TARGET_UID)
    159                 .setPackageName(TARGET_PACKAGE_NAME)
    160                 .setType(Anomaly.AnomalyType.WAKEUP_ALARM)
    161                 .setTargetSdkVersion(TARGET_SDK)
    162                 .setBackgroundRestrictionEnabled(TARGET_BACKGROUND_RESTRICTION_ON)
    163                 .setWakeupAlarmCount(ANOMALY_WAKEUP_FREQUENCY)
    164                 .build();
    165 
    166         mWakeupAlarmAnomalyDetector = spy(
    167                 new WakeupAlarmAnomalyDetector(mContext, mPolicy, mAnomalyUtils));
    168         mWakeupAlarmAnomalyDetector.mBatteryUtils = mBatteryUtils;
    169     }
    170 
    171     @Test
    172     public void testDetectAnomalies_containsAnomaly_detectIt() {
    173         doReturn(-1).when(mBatteryUtils).getPackageUid(nullable(String.class));
    174         doReturn(ANOMALY_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid(
    175                 mAnomalyUid);
    176         doReturn(ANOMALY_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid(
    177                 mTargetUid);
    178         doReturn(NORMAL_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid(
    179                 mNormalUid);
    180 
    181         List<Anomaly> mAnomalies = mWakeupAlarmAnomalyDetector.detectAnomalies(mBatteryStatsHelper);
    182 
    183         assertThat(mAnomalies).containsExactly(mAnomaly, mTargetAnomaly);
    184     }
    185 
    186     @Test
    187     public void testDetectAnomalies_detectTargetAnomaly_detectIt() {
    188         doReturn(TARGET_UID).when(mBatteryUtils).getPackageUid(TARGET_PACKAGE_NAME);
    189         doReturn(ANOMALY_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid(
    190                 mAnomalyUid);
    191         doReturn(ANOMALY_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid(
    192                 mTargetUid);
    193         doReturn(NORMAL_WAKEUP_COUNT).when(mWakeupAlarmAnomalyDetector).getWakeupAlarmCountFromUid(
    194                 mNormalUid);
    195 
    196         List<Anomaly> mAnomalies = mWakeupAlarmAnomalyDetector.detectAnomalies(mBatteryStatsHelper,
    197                 TARGET_PACKAGE_NAME);
    198 
    199         assertThat(mAnomalies).containsExactly(mTargetAnomaly);
    200     }
    201 
    202     @Test
    203     public void testGetWakeupAlarmCountFromUid_countCorrect() {
    204         final ArrayMap<String, BatteryStats.Uid.Pkg> packageStats = new ArrayMap<>();
    205         final ArrayMap<String, BatteryStats.Counter> alarms = new ArrayMap<>();
    206         doReturn(alarms).when(mPkg).getWakeupAlarmStats();
    207         doReturn(NORMAL_WAKEUP_COUNT).when(mCounter).getCountLocked(anyInt());
    208         doReturn(packageStats).when(mAnomalyUid).getPackageStats();
    209         packageStats.put("", mPkg);
    210         alarms.put("1", mCounter);
    211         alarms.put("2", mCounter);
    212 
    213         assertThat(mWakeupAlarmAnomalyDetector.getWakeupAlarmCountFromUid(mAnomalyUid)).isEqualTo(
    214                 2 * NORMAL_WAKEUP_COUNT);
    215     }
    216 
    217     @Test
    218     public void testGetWakeupAlarmCountFromUid_filterOutBlacklistedTags() {
    219         final ArrayMap<String, BatteryStats.Uid.Pkg> packageStats = new ArrayMap<>();
    220         final ArrayMap<String, BatteryStats.Counter> alarms = new ArrayMap<>();
    221         doReturn(alarms).when(mPkg).getWakeupAlarmStats();
    222         doReturn(NORMAL_WAKEUP_COUNT).when(mCounter).getCountLocked(anyInt());
    223         doReturn(BLACKLISTED_WAKEUP_COUNT).when(mCounter2).getCountLocked(anyInt());
    224         doReturn(packageStats).when(mAnomalyUid).getPackageStats();
    225         packageStats.put("", mPkg);
    226         alarms.put("allowedTag", mCounter);
    227         alarms.put("blacklistedTag", mCounter2);
    228 
    229         assertThat(mWakeupAlarmAnomalyDetector.getWakeupAlarmCountFromUid(mAnomalyUid)).isEqualTo(
    230                 NORMAL_WAKEUP_COUNT);
    231     }
    232 }
    233