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 import static org.mockito.ArgumentMatchers.nullable; 21 import static org.mockito.Matchers.any; 22 import static org.mockito.Matchers.anyInt; 23 import static org.mockito.Matchers.anyLong; 24 import static org.mockito.Matchers.eq; 25 import static org.mockito.Mockito.doReturn; 26 import static org.mockito.Mockito.spy; 27 import static org.mockito.Mockito.when; 28 29 import android.content.Context; 30 import android.content.pm.ApplicationInfo; 31 import android.content.pm.PackageManager; 32 import android.os.BatteryStats; 33 import android.text.format.DateUtils; 34 35 import com.android.internal.os.BatterySipper; 36 import com.android.internal.os.BatteryStatsHelper; 37 import com.android.settings.fuelgauge.BatteryUtils; 38 import com.android.settings.fuelgauge.anomaly.Anomaly; 39 import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; 40 import com.android.settings.fuelgauge.anomaly.AnomalyUtils; 41 import com.android.settings.fuelgauge.anomaly.action.AnomalyAction; 42 import com.android.settings.testutils.SettingsRobolectricTestRunner; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 import org.robolectric.RuntimeEnvironment; 50 import org.robolectric.util.ReflectionHelpers; 51 52 import java.util.ArrayList; 53 import java.util.List; 54 55 @RunWith(SettingsRobolectricTestRunner.class) 56 public class WakeLockAnomalyDetectorTest { 57 58 private static final String TARGET_PACKAGE_NAME = "com.android.app"; 59 private static final long ANOMALY_WAKELOCK_TIME_MS = 2 * DateUtils.HOUR_IN_MILLIS; 60 private static final long NORMAL_WAKELOCK_TIME_MS = DateUtils.SECOND_IN_MILLIS; 61 private static final long WAKELOCK_THRESHOLD_MS = DateUtils.HOUR_IN_MILLIS; 62 private static final int ANOMALY_UID = 111; 63 private static final int NORMAL_UID = 222; 64 private static final int TARGET_UID = 333; 65 private static final int INACTIVE_UID = 444; 66 @Mock 67 private BatteryStatsHelper mBatteryStatsHelper; 68 @Mock 69 private BatterySipper mAnomalySipper; 70 @Mock 71 private BatterySipper mTargetSipper; 72 @Mock 73 private BatterySipper mNormalSipper; 74 @Mock 75 private BatterySipper mInactiveSipper; 76 @Mock 77 private BatteryStats.Uid mAnomalyUid; 78 @Mock 79 private BatteryStats.Uid mNormalUid; 80 @Mock 81 private BatteryStats.Uid mTargetUid; 82 @Mock 83 private BatteryStats.Uid mInactiveUid; 84 @Mock 85 private BatteryUtils mBatteryUtils; 86 @Mock 87 private PackageManager mPackageManager; 88 @Mock 89 private ApplicationInfo mApplicationInfo; 90 @Mock 91 private AnomalyDetectionPolicy mPolicy; 92 @Mock 93 private AnomalyAction mAnomalyAction; 94 @Mock 95 private AnomalyUtils mAnomalyUtils; 96 97 private WakeLockAnomalyDetector mWakelockAnomalyDetector; 98 private Context mContext; 99 private List<BatterySipper> mUsageList; 100 private Anomaly mAnomaly; 101 private Anomaly mTargetAnomaly; 102 103 @Before 104 public void setUp() throws Exception { 105 MockitoAnnotations.initMocks(this); 106 107 mContext = spy(RuntimeEnvironment.application); 108 ReflectionHelpers.setField(mPolicy, "wakeLockThreshold", WAKELOCK_THRESHOLD_MS); 109 110 doReturn(false).when(mBatteryUtils).shouldHideSipper(nullable(BatterySipper.class)); 111 doReturn(mPackageManager).when(mContext).getPackageManager(); 112 doReturn(mApplicationInfo).when(mPackageManager) 113 .getApplicationInfo(nullable(String.class), anyInt()); 114 doReturn(true).when(mAnomalyAction).isActionActive(any()); 115 doReturn(mAnomalyAction).when(mAnomalyUtils).getAnomalyAction(any()); 116 117 mWakelockAnomalyDetector = 118 spy(new WakeLockAnomalyDetector(mContext, mPolicy, mAnomalyUtils)); 119 mWakelockAnomalyDetector.mBatteryUtils = mBatteryUtils; 120 121 mAnomalySipper.uidObj = mAnomalyUid; 122 doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector) 123 .getBackgroundTotalDurationMs(eq(mAnomalyUid), anyLong()); 124 doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector) 125 .getCurrentDurationMs(eq(mAnomalyUid), anyLong()); 126 doReturn(ANOMALY_UID).when(mAnomalyUid).getUid(); 127 128 mNormalSipper.uidObj = mNormalUid; 129 doReturn(NORMAL_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector) 130 .getBackgroundTotalDurationMs(eq(mNormalUid), anyLong()); 131 doReturn(0L).when(mWakelockAnomalyDetector) 132 .getCurrentDurationMs(eq(mNormalUid), anyLong()); 133 doReturn(NORMAL_UID).when(mNormalUid).getUid(); 134 135 mTargetSipper.uidObj = mTargetUid; 136 doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector) 137 .getBackgroundTotalDurationMs(eq(mTargetUid), anyLong()); 138 doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector) 139 .getCurrentDurationMs(eq(mTargetUid), anyLong()); 140 doReturn(TARGET_UID).when(mTargetUid).getUid(); 141 142 mInactiveSipper.uidObj = mInactiveUid; 143 doReturn(ANOMALY_WAKELOCK_TIME_MS).when(mWakelockAnomalyDetector) 144 .getBackgroundTotalDurationMs(eq(mInactiveUid), anyLong()); 145 doReturn(0L).when(mWakelockAnomalyDetector) 146 .getCurrentDurationMs(eq(mInactiveUid), anyLong()); 147 doReturn(INACTIVE_UID).when(mInactiveUid).getUid(); 148 149 mUsageList = new ArrayList<>(); 150 mUsageList.add(mAnomalySipper); 151 mUsageList.add(mNormalSipper); 152 mUsageList.add(mTargetSipper); 153 mUsageList.add(mInactiveSipper); 154 when(mBatteryStatsHelper.getUsageList()).thenReturn(mUsageList); 155 156 mAnomaly = createWakeLockAnomaly(ANOMALY_UID); 157 mTargetAnomaly = createWakeLockAnomaly(TARGET_UID); 158 } 159 160 @Test 161 public void testDetectAnomalies_containsAnomaly_detectIt() { 162 doReturn(BatteryUtils.UID_NULL).when(mBatteryUtils).getPackageUid(nullable(String.class)); 163 164 List<Anomaly> mAnomalies = mWakelockAnomalyDetector.detectAnomalies(mBatteryStatsHelper); 165 166 assertThat(mAnomalies).containsExactly(mAnomaly, mTargetAnomaly); 167 } 168 169 @Test 170 public void testDetectAnomalies_containsTargetPackage_detectIt() { 171 doReturn(TARGET_UID).when(mBatteryUtils).getPackageUid(TARGET_PACKAGE_NAME); 172 173 List<Anomaly> mAnomalies = 174 mWakelockAnomalyDetector.detectAnomalies(mBatteryStatsHelper, TARGET_PACKAGE_NAME); 175 176 assertThat(mAnomalies).containsExactly(mTargetAnomaly); 177 } 178 179 @Test 180 public void testContainsThresholdFromPolicy() { 181 assertThat(mWakelockAnomalyDetector.mWakeLockThresholdMs).isEqualTo(WAKELOCK_THRESHOLD_MS); 182 } 183 184 private Anomaly createWakeLockAnomaly(int uid) { 185 return new Anomaly.Builder() 186 .setUid(uid) 187 .setType(Anomaly.AnomalyType.WAKE_LOCK) 188 .setWakeLockTimeMs(ANOMALY_WAKELOCK_TIME_MS) 189 .build(); 190 } 191 } 192