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.testutils; 18 19 import static org.mockito.Mockito.when; 20 21 import android.app.settings.SettingsEnums; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.hardware.usb.UsbManager; 25 import android.hardware.usb.UsbPort; 26 import android.hardware.usb.UsbPortStatus; 27 import android.os.BatteryManager; 28 import android.os.UserManager; 29 30 import androidx.room.Room; 31 32 import com.android.settings.DisplaySettings; 33 import com.android.settings.display.ScreenTimeoutSettings; 34 import com.android.settings.fuelgauge.batteryusage.BatteryInformation; 35 import com.android.settings.fuelgauge.batteryusage.ConvertUtils; 36 import com.android.settings.fuelgauge.batteryusage.DeviceBatteryState; 37 import com.android.settings.fuelgauge.batteryusage.PowerAnomalyEvent; 38 import com.android.settings.fuelgauge.batteryusage.PowerAnomalyEventList; 39 import com.android.settings.fuelgauge.batteryusage.PowerAnomalyKey; 40 import com.android.settings.fuelgauge.batteryusage.PowerAnomalyType; 41 import com.android.settings.fuelgauge.batteryusage.WarningBannerInfo; 42 import com.android.settings.fuelgauge.batteryusage.WarningItemInfo; 43 import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventDao; 44 import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity; 45 import com.android.settings.fuelgauge.batteryusage.db.BatteryState; 46 import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDao; 47 import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase; 48 49 import com.google.common.collect.ImmutableList; 50 51 import org.robolectric.Shadows; 52 53 import java.util.ArrayList; 54 import java.util.List; 55 56 public class BatteryTestUtils { 57 getChargingIntent()58 public static Intent getChargingIntent() { 59 return getCustomBatteryIntent( 60 BatteryManager.BATTERY_PLUGGED_AC, 61 50 /* level */, 62 100 /* scale */, 63 BatteryManager.BATTERY_STATUS_CHARGING); 64 } 65 getDischargingIntent()66 public static Intent getDischargingIntent() { 67 return getCustomBatteryIntent( 68 0 /* plugged */, 69 10 /* level */, 70 100 /* scale */, 71 BatteryManager.BATTERY_STATUS_DISCHARGING); 72 } 73 74 /** 75 * Sets the work profile mode. 76 */ setWorkProfile(Context context)77 public static void setWorkProfile(Context context) { 78 final UserManager userManager = context.getSystemService(UserManager.class); 79 Shadows.shadowOf(userManager).setManagedProfile(true); 80 Shadows.shadowOf(userManager).setIsSystemUser(false); 81 } 82 83 /** 84 * Creates and sets up the in-memory {@link BatteryStateDatabase}. 85 */ setUpBatteryStateDatabase(Context context)86 public static BatteryStateDatabase setUpBatteryStateDatabase(Context context) { 87 final BatteryStateDatabase inMemoryDatabase = 88 Room.inMemoryDatabaseBuilder(context, BatteryStateDatabase.class) 89 .allowMainThreadQueries() 90 .build(); 91 BatteryStateDatabase.setBatteryStateDatabase(inMemoryDatabase); 92 return inMemoryDatabase; 93 } 94 95 /** 96 * Inserts a fake data into the database for testing. 97 */ insertDataToBatteryStateTable( Context context, long timestamp, String packageName)98 public static void insertDataToBatteryStateTable( 99 Context context, long timestamp, String packageName) { 100 insertDataToBatteryStateTable( 101 context, timestamp, packageName, /*multiple=*/ false, /*isFullChargeStart=*/ false); 102 } 103 104 /** 105 * Inserts a fake data into the database for testing. 106 */ insertDataToBatteryStateTable( Context context, long timestamp, String packageName, boolean isFullChargeStart)107 public static void insertDataToBatteryStateTable( 108 Context context, long timestamp, String packageName, boolean isFullChargeStart) { 109 insertDataToBatteryStateTable( 110 context, timestamp, packageName, /*multiple=*/ false, isFullChargeStart); 111 } 112 113 /** 114 * Inserts a fake data into the database for testing. 115 */ insertDataToBatteryStateTable( Context context, long timestamp, String packageName, boolean multiple, boolean isFullChargeStart)116 public static void insertDataToBatteryStateTable( 117 Context context, long timestamp, String packageName, boolean multiple, 118 boolean isFullChargeStart) { 119 DeviceBatteryState deviceBatteryState = 120 DeviceBatteryState 121 .newBuilder() 122 .setBatteryLevel(31) 123 .setBatteryStatus(0) 124 .setBatteryHealth(0) 125 .build(); 126 BatteryInformation batteryInformation = 127 BatteryInformation 128 .newBuilder() 129 .setDeviceBatteryState(deviceBatteryState) 130 .setIsHidden(true) 131 .setBootTimestamp(timestamp - 1) 132 .setZoneId("Europe/Paris") 133 .setAppLabel("Settings") 134 .setTotalPower(100f) 135 .setConsumePower(0.3f) 136 .setPercentOfTotal(10f) 137 .setDrainType(1) 138 .setForegroundUsageTimeInMs(60000) 139 .setBackgroundUsageTimeInMs(10000) 140 .setForegroundUsageConsumePower(0.1f) 141 .setForegroundServiceUsageConsumePower(0.05f) 142 .setBackgroundUsageConsumePower(0.1f) 143 .setCachedUsageConsumePower(0.05f) 144 .build(); 145 146 final BatteryState state = 147 new BatteryState( 148 /*uid=*/ 1001L, 149 /*userId=*/ 100L, 150 packageName, 151 timestamp, 152 /*consumerType=*/ 2, 153 isFullChargeStart, 154 ConvertUtils.convertBatteryInformationToString(batteryInformation), 155 ""); 156 BatteryStateDao dao = 157 BatteryStateDatabase.getInstance(context).batteryStateDao(); 158 if (multiple) { 159 dao.insertAll(ImmutableList.of(state)); 160 } else { 161 dao.insert(state); 162 } 163 } 164 165 /** 166 * Inserts a fake data into the database for testing. 167 */ insertDataToAppUsageEventTable( Context context, long userId, long timestamp, String packageName)168 public static void insertDataToAppUsageEventTable( 169 Context context, long userId, long timestamp, String packageName) { 170 insertDataToAppUsageEventTable( 171 context, userId, timestamp, packageName, /*multiple=*/ false); 172 } 173 174 /** 175 * Inserts a fake data into the database for testing. 176 */ insertDataToAppUsageEventTable( Context context, long userId, long timestamp, String packageName, boolean multiple)177 public static void insertDataToAppUsageEventTable( 178 Context context, long userId, long timestamp, String packageName, boolean multiple) { 179 final AppUsageEventEntity entity = 180 new AppUsageEventEntity( 181 /*uid=*/ 101L, 182 userId, 183 timestamp, 184 /*appUsageEventType=*/ 2, 185 packageName, 186 /*instanceId=*/ 10001, 187 /*taskRootPackageName=*/ "com.android.settings"); 188 AppUsageEventDao dao = 189 BatteryStateDatabase.getInstance(context).appUsageEventDao(); 190 if (multiple) { 191 dao.insertAll(ImmutableList.of(entity)); 192 } else { 193 dao.insert(entity); 194 } 195 } 196 197 /** 198 * Gets customized battery changed intent. 199 */ getCustomBatteryIntent(int plugged, int level, int scale, int status)200 public static Intent getCustomBatteryIntent(int plugged, int level, int scale, int status) { 201 Intent intent = new Intent(); 202 intent.putExtra(BatteryManager.EXTRA_PLUGGED, plugged); 203 intent.putExtra(BatteryManager.EXTRA_LEVEL, level); 204 intent.putExtra(BatteryManager.EXTRA_SCALE, scale); 205 intent.putExtra(BatteryManager.EXTRA_STATUS, status); 206 207 return intent; 208 } 209 210 /** 211 * Configures the incompatible charger environment. 212 */ setupIncompatibleEvent( UsbPort mockUsbPort, UsbManager mockUsbManager, UsbPortStatus mockUsbPortStatus)213 public static void setupIncompatibleEvent( 214 UsbPort mockUsbPort, UsbManager mockUsbManager, UsbPortStatus mockUsbPortStatus) { 215 final List<UsbPort> usbPorts = new ArrayList<>(); 216 usbPorts.add(mockUsbPort); 217 when(mockUsbManager.getPorts()).thenReturn(usbPorts); 218 when(mockUsbPort.getStatus()).thenReturn(mockUsbPortStatus); 219 when(mockUsbPort.supportsComplianceWarnings()).thenReturn(true); 220 when(mockUsbPortStatus.isConnected()).thenReturn(true); 221 when(mockUsbPortStatus.getComplianceWarnings()) 222 .thenReturn(new int[]{UsbPortStatus.COMPLIANCE_WARNING_OTHER}); 223 } 224 225 /** 226 * Create an empty power anomaly event list proto. 227 */ createEmptyPowerAnomalyEventList()228 public static PowerAnomalyEventList createEmptyPowerAnomalyEventList() { 229 return PowerAnomalyEventList.getDefaultInstance(); 230 } 231 232 /** 233 * Create an non-empty power anomaly event list proto. 234 */ createNonEmptyPowerAnomalyEventList()235 public static PowerAnomalyEventList createNonEmptyPowerAnomalyEventList() { 236 return PowerAnomalyEventList.newBuilder() 237 .addPowerAnomalyEvents(0, createAdaptiveBrightnessAnomalyEvent()) 238 .addPowerAnomalyEvents(1, createScreenTimeoutAnomalyEvent()) 239 .build(); 240 } 241 242 /** 243 * Create a power anomaly event proto of adaptive brightness. 244 */ createAdaptiveBrightnessAnomalyEvent()245 public static PowerAnomalyEvent createAdaptiveBrightnessAnomalyEvent() { 246 return PowerAnomalyEvent.newBuilder() 247 .setEventId("BrightnessAnomaly") 248 .setType(PowerAnomalyType.TYPE_SETTINGS_BANNER) 249 .setKey(PowerAnomalyKey.KEY_BRIGHTNESS) 250 .setDismissRecordKey(PowerAnomalyKey.KEY_BRIGHTNESS.name()) 251 .setScore(1.2f) 252 .setWarningBannerInfo(WarningBannerInfo.newBuilder() 253 .setMainButtonDestination(DisplaySettings.class.getName()) 254 .setMainButtonSourceMetricsCategory(SettingsEnums.DISPLAY) 255 .setMainButtonSourceHighlightKey("auto_brightness_entry") 256 .build()) 257 .build(); 258 } 259 260 /** 261 * Create a power anomaly event proto of screen timeout. 262 */ createScreenTimeoutAnomalyEvent()263 public static PowerAnomalyEvent createScreenTimeoutAnomalyEvent() { 264 return PowerAnomalyEvent.newBuilder() 265 .setEventId("ScreenTimeoutAnomaly") 266 .setType(PowerAnomalyType.TYPE_SETTINGS_BANNER) 267 .setKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT) 268 .setDismissRecordKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name()) 269 .setScore(1.1f) 270 .setWarningBannerInfo(WarningBannerInfo.newBuilder() 271 .setMainButtonDestination(ScreenTimeoutSettings.class.getName()) 272 .setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT) 273 .setMainButtonSourceHighlightKey("60000") 274 .build()) 275 .build(); 276 } 277 278 /** 279 * Create a power anomaly event proto of app anomaly. 280 */ createAppAnomalyEvent()281 public static PowerAnomalyEvent createAppAnomalyEvent() { 282 return PowerAnomalyEvent.newBuilder() 283 .setEventId("AppAnomaly") 284 .setType(PowerAnomalyType.TYPE_APPS_ITEM) 285 .setKey(PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL) 286 .setDismissRecordKey("KEY_APP_1") 287 .setScore(2.0f) 288 .setWarningItemInfo(WarningItemInfo.newBuilder() 289 .setStartTimestamp(1694361600000L) // 2023-09-11 00:00:00 290 .setEndTimestamp(1694368800000L) // 2023-09-11 02:00:00 291 .build()) 292 .build(); 293 } 294 } 295