1ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei/* 2ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * Copyright (C) 2017 The Android Open Source Project 3ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * 4ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * Licensed under the Apache License, Version 2.0 (the "License"); 5ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * you may not use this file except in compliance with the License. 6ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * You may obtain a copy of the License at 7ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * 8ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * http://www.apache.org/licenses/LICENSE-2.0 9ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * 10ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * Unless required by applicable law or agreed to in writing, software 11ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * distributed under the License is distributed on an "AS IS" BASIS, 12ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * See the License for the specific language governing permissions and 14ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei * limitations under the License. 15ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei */ 16ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 17ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleipackage com.android.settings.fuelgauge.anomaly.checker; 18ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 19ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static com.google.common.truth.Truth.assertThat; 20ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 21ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.ArgumentMatchers.nullable; 22ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.Matchers.any; 23ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.Matchers.anyLong; 24ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.Matchers.eq; 25ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.Mockito.doReturn; 26ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport static org.mockito.Mockito.spy; 27ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 28ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport android.content.Context; 29ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport android.content.pm.ApplicationInfo; 30ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport android.os.BatteryStats; 31ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport android.text.format.DateUtils; 32ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 33ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.internal.os.BatterySipper; 34ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.internal.os.BatteryStatsHelper; 35ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.settings.TestConfig; 36ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.settings.fuelgauge.BatteryUtils; 37ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.settings.fuelgauge.anomaly.Anomaly; 38ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; 39bfc2b11b9357c4508756243f540760458611b3b8jackqdyuleiimport com.android.settings.fuelgauge.anomaly.AnomalyUtils; 40ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.settings.fuelgauge.anomaly.action.AnomalyAction; 41ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport com.android.settings.testutils.SettingsRobolectricTestRunner; 42ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 43ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.junit.Before; 44ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.junit.Test; 45ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.junit.runner.RunWith; 46ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.mockito.Mock; 47ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.mockito.MockitoAnnotations; 48ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.robolectric.RuntimeEnvironment; 49ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport org.robolectric.annotation.Config; 50b96906a082511a5390700818257c8a215637b9e9jackqdyuleiimport org.robolectric.util.ReflectionHelpers; 51ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 52ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport java.util.ArrayList; 53ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleiimport java.util.List; 54ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 55ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei@RunWith(SettingsRobolectricTestRunner.class) 56ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) 57ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyuleipublic class BluetoothScanAnomalyDetectorTest { 58ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private static final String TARGET_PACKAGE_NAME = "com.android.app"; 59ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private static final int ANOMALY_UID = 111; 60ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private static final int NORMAL_UID = 222; 61ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private static final int TARGET_UID = 333; 62ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private static final long ANOMALY_BLUETOOTH_SCANNING_TIME = DateUtils.HOUR_IN_MILLIS; 63ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private static final long NORMAL_BLUETOOTH_SCANNING_TIME = DateUtils.MINUTE_IN_MILLIS; 64ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock 65ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private BatteryStatsHelper mBatteryStatsHelper; 66ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock 67ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private BatterySipper mAnomalySipper; 68ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock 69ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private BatterySipper mNormalSipper; 70ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock 71ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private BatterySipper mTargetSipper; 72ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock 73ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private BatteryStats.Uid mAnomalyUid; 74ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock 75ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private BatteryStats.Uid mNormalUid; 76ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock 77ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private BatteryStats.Uid mTargetUid; 78ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock 79ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private BatteryUtils mBatteryUtils; 80ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock 81ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private AnomalyDetectionPolicy mPolicy; 82ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Mock 83ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private AnomalyAction mAnomalyAction; 84bfc2b11b9357c4508756243f540760458611b3b8jackqdyulei @Mock 85bfc2b11b9357c4508756243f540760458611b3b8jackqdyulei private AnomalyUtils mAnomalyUtils; 86ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 87ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private BluetoothScanAnomalyDetector mBluetoothScanAnomalyDetector; 88ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private Context mContext; 89ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private List<BatterySipper> mUsageList; 90ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 91ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Before 92ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public void setUp() { 93ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei MockitoAnnotations.initMocks(this); 94ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 95ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mContext = spy(RuntimeEnvironment.application); 96b96906a082511a5390700818257c8a215637b9e9jackqdyulei ReflectionHelpers.setField(mPolicy, "bluetoothScanThreshold", 97b96906a082511a5390700818257c8a215637b9e9jackqdyulei 30 * DateUtils.MINUTE_IN_MILLIS); 98bfc2b11b9357c4508756243f540760458611b3b8jackqdyulei doReturn(mAnomalyAction).when(mAnomalyUtils).getAnomalyAction(any()); 99ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 100ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mAnomalySipper.uidObj = mAnomalyUid; 101ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(ANOMALY_UID).when(mAnomalyUid).getUid(); 102ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mNormalSipper.uidObj = mNormalUid; 103ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(NORMAL_UID).when(mNormalUid).getUid(); 104ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mTargetSipper.uidObj = mTargetUid; 105ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(TARGET_UID).when(mTargetUid).getUid(); 106ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 107ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mUsageList = new ArrayList<>(); 108ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mUsageList.add(mAnomalySipper); 109ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mUsageList.add(mNormalSipper); 110ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mUsageList.add(mTargetSipper); 111ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(mUsageList).when(mBatteryStatsHelper).getUsageList(); 112ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 113bfc2b11b9357c4508756243f540760458611b3b8jackqdyulei mBluetoothScanAnomalyDetector = spy(new BluetoothScanAnomalyDetector(mContext, mPolicy, 114bfc2b11b9357c4508756243f540760458611b3b8jackqdyulei mAnomalyUtils)); 115ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBluetoothScanAnomalyDetector.mBatteryUtils = mBatteryUtils; 116ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(false).when(mBatteryUtils).shouldHideSipper(any()); 117ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(true).when(mAnomalyAction).isActionActive(any()); 118ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 119ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(ANOMALY_BLUETOOTH_SCANNING_TIME).when( 120ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBluetoothScanAnomalyDetector).getBluetoothUnoptimizedBgTimeMs(eq(mAnomalyUid), 121ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei anyLong()); 122ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(ANOMALY_BLUETOOTH_SCANNING_TIME).when( 123ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBluetoothScanAnomalyDetector).getBluetoothUnoptimizedBgTimeMs(eq(mTargetUid), 124ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei anyLong()); 125ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(NORMAL_BLUETOOTH_SCANNING_TIME).when( 126ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBluetoothScanAnomalyDetector).getBluetoothUnoptimizedBgTimeMs(eq(mNormalUid), 127ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei anyLong()); 128ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei } 129ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 130ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Test 131ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public void testDetectAnomalies_containsAnomaly_detectIt() { 132ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(-1).when(mBatteryUtils).getPackageUid(nullable(String.class)); 133ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei final Anomaly anomaly = createBluetoothAnomaly(ANOMALY_UID); 134ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei final Anomaly targetAnomaly = createBluetoothAnomaly(TARGET_UID); 135ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 136ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei List<Anomaly> mAnomalies = mBluetoothScanAnomalyDetector.detectAnomalies( 137ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBatteryStatsHelper); 138ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 139ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(mAnomalies).containsExactly(anomaly, targetAnomaly); 140ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei } 141ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 142ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei @Test 143ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei public void testDetectAnomalies_detectTargetAnomaly_detectIt() { 144ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei doReturn(TARGET_UID).when(mBatteryUtils).getPackageUid(TARGET_PACKAGE_NAME); 145ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei final Anomaly targetAnomaly = createBluetoothAnomaly(TARGET_UID); 146ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 147ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei List<Anomaly> mAnomalies = mBluetoothScanAnomalyDetector.detectAnomalies( 148ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei mBatteryStatsHelper, TARGET_PACKAGE_NAME); 149ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 150ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei assertThat(mAnomalies).containsExactly(targetAnomaly); 151ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 152ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei } 153ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 154ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei private Anomaly createBluetoothAnomaly(int uid) { 155ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei return new Anomaly.Builder() 156ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei .setUid(uid) 157ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei .setType(Anomaly.AnomalyType.BLUETOOTH_SCAN) 158edfebbaa4f3ffa98c99e1e41b054853ccbff06c7jackqdyulei .setBluetoothScanningTimeMs(ANOMALY_BLUETOOTH_SCANNING_TIME) 159ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei .build(); 160ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei } 161ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei 162ec8e127ed3a616a7ca223a5bc6d9c4bbc036cd90jackqdyulei} 163