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.anyLong; 24 import static org.mockito.Matchers.eq; 25 import static org.mockito.Mockito.doReturn; 26 import static org.mockito.Mockito.spy; 27 28 import android.content.Context; 29 import android.content.pm.ApplicationInfo; 30 import android.os.BatteryStats; 31 import android.text.format.DateUtils; 32 33 import com.android.internal.os.BatterySipper; 34 import com.android.internal.os.BatteryStatsHelper; 35 import com.android.settings.TestConfig; 36 import com.android.settings.fuelgauge.BatteryUtils; 37 import com.android.settings.fuelgauge.anomaly.Anomaly; 38 import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; 39 import com.android.settings.fuelgauge.anomaly.AnomalyUtils; 40 import com.android.settings.fuelgauge.anomaly.action.AnomalyAction; 41 import com.android.settings.testutils.SettingsRobolectricTestRunner; 42 43 import org.junit.Before; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.mockito.Mock; 47 import org.mockito.MockitoAnnotations; 48 import org.robolectric.RuntimeEnvironment; 49 import org.robolectric.annotation.Config; 50 import org.robolectric.util.ReflectionHelpers; 51 52 import java.util.ArrayList; 53 import java.util.List; 54 55 @RunWith(SettingsRobolectricTestRunner.class) 56 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) 57 public class BluetoothScanAnomalyDetectorTest { 58 private static final String TARGET_PACKAGE_NAME = "com.android.app"; 59 private static final int ANOMALY_UID = 111; 60 private static final int NORMAL_UID = 222; 61 private static final int TARGET_UID = 333; 62 private static final long ANOMALY_BLUETOOTH_SCANNING_TIME = DateUtils.HOUR_IN_MILLIS; 63 private static final long NORMAL_BLUETOOTH_SCANNING_TIME = DateUtils.MINUTE_IN_MILLIS; 64 @Mock 65 private BatteryStatsHelper mBatteryStatsHelper; 66 @Mock 67 private BatterySipper mAnomalySipper; 68 @Mock 69 private BatterySipper mNormalSipper; 70 @Mock 71 private BatterySipper mTargetSipper; 72 @Mock 73 private BatteryStats.Uid mAnomalyUid; 74 @Mock 75 private BatteryStats.Uid mNormalUid; 76 @Mock 77 private BatteryStats.Uid mTargetUid; 78 @Mock 79 private BatteryUtils mBatteryUtils; 80 @Mock 81 private AnomalyDetectionPolicy mPolicy; 82 @Mock 83 private AnomalyAction mAnomalyAction; 84 @Mock 85 private AnomalyUtils mAnomalyUtils; 86 87 private BluetoothScanAnomalyDetector mBluetoothScanAnomalyDetector; 88 private Context mContext; 89 private List<BatterySipper> mUsageList; 90 91 @Before 92 public void setUp() { 93 MockitoAnnotations.initMocks(this); 94 95 mContext = spy(RuntimeEnvironment.application); 96 ReflectionHelpers.setField(mPolicy, "bluetoothScanThreshold", 97 30 * DateUtils.MINUTE_IN_MILLIS); 98 doReturn(mAnomalyAction).when(mAnomalyUtils).getAnomalyAction(any()); 99 100 mAnomalySipper.uidObj = mAnomalyUid; 101 doReturn(ANOMALY_UID).when(mAnomalyUid).getUid(); 102 mNormalSipper.uidObj = mNormalUid; 103 doReturn(NORMAL_UID).when(mNormalUid).getUid(); 104 mTargetSipper.uidObj = mTargetUid; 105 doReturn(TARGET_UID).when(mTargetUid).getUid(); 106 107 mUsageList = new ArrayList<>(); 108 mUsageList.add(mAnomalySipper); 109 mUsageList.add(mNormalSipper); 110 mUsageList.add(mTargetSipper); 111 doReturn(mUsageList).when(mBatteryStatsHelper).getUsageList(); 112 113 mBluetoothScanAnomalyDetector = spy(new BluetoothScanAnomalyDetector(mContext, mPolicy, 114 mAnomalyUtils)); 115 mBluetoothScanAnomalyDetector.mBatteryUtils = mBatteryUtils; 116 doReturn(false).when(mBatteryUtils).shouldHideSipper(any()); 117 doReturn(true).when(mAnomalyAction).isActionActive(any()); 118 119 doReturn(ANOMALY_BLUETOOTH_SCANNING_TIME).when( 120 mBluetoothScanAnomalyDetector).getBluetoothUnoptimizedBgTimeMs(eq(mAnomalyUid), 121 anyLong()); 122 doReturn(ANOMALY_BLUETOOTH_SCANNING_TIME).when( 123 mBluetoothScanAnomalyDetector).getBluetoothUnoptimizedBgTimeMs(eq(mTargetUid), 124 anyLong()); 125 doReturn(NORMAL_BLUETOOTH_SCANNING_TIME).when( 126 mBluetoothScanAnomalyDetector).getBluetoothUnoptimizedBgTimeMs(eq(mNormalUid), 127 anyLong()); 128 } 129 130 @Test 131 public void testDetectAnomalies_containsAnomaly_detectIt() { 132 doReturn(-1).when(mBatteryUtils).getPackageUid(nullable(String.class)); 133 final Anomaly anomaly = createBluetoothAnomaly(ANOMALY_UID); 134 final Anomaly targetAnomaly = createBluetoothAnomaly(TARGET_UID); 135 136 List<Anomaly> mAnomalies = mBluetoothScanAnomalyDetector.detectAnomalies( 137 mBatteryStatsHelper); 138 139 assertThat(mAnomalies).containsExactly(anomaly, targetAnomaly); 140 } 141 142 @Test 143 public void testDetectAnomalies_detectTargetAnomaly_detectIt() { 144 doReturn(TARGET_UID).when(mBatteryUtils).getPackageUid(TARGET_PACKAGE_NAME); 145 final Anomaly targetAnomaly = createBluetoothAnomaly(TARGET_UID); 146 147 List<Anomaly> mAnomalies = mBluetoothScanAnomalyDetector.detectAnomalies( 148 mBatteryStatsHelper, TARGET_PACKAGE_NAME); 149 150 assertThat(mAnomalies).containsExactly(targetAnomaly); 151 152 } 153 154 private Anomaly createBluetoothAnomaly(int uid) { 155 return new Anomaly.Builder() 156 .setUid(uid) 157 .setType(Anomaly.AnomalyType.BLUETOOTH_SCAN) 158 .setBluetoothScanningTimeMs(ANOMALY_BLUETOOTH_SCANNING_TIME) 159 .build(); 160 } 161 162 } 163