1 /* 2 * Copyright (C) 2016 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 package com.android.settings.fuelgauge; 17 18 import static com.google.common.truth.Truth.assertThat; 19 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.ArgumentMatchers.anyString; 22 import static org.mockito.ArgumentMatchers.eq; 23 import static org.mockito.Mockito.doReturn; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.when; 27 28 import android.content.Context; 29 import android.content.pm.ApplicationInfo; 30 import android.content.pm.PackageManager; 31 import android.content.pm.PackageManager.NameNotFoundException; 32 import android.os.BatteryConsumer; 33 import android.os.Handler; 34 import android.os.Process; 35 import android.os.UidBatteryConsumer; 36 import android.os.UserBatteryConsumer; 37 import android.os.UserManager; 38 39 import com.android.settings.R; 40 import com.android.settings.fuelgauge.BatteryEntry.NameAndIcon; 41 42 import org.junit.Before; 43 import org.junit.Rule; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.mockito.Answers; 47 import org.mockito.Mock; 48 import org.mockito.junit.MockitoJUnit; 49 import org.mockito.junit.MockitoRule; 50 import org.robolectric.RobolectricTestRunner; 51 import org.robolectric.RuntimeEnvironment; 52 53 import java.util.Locale; 54 55 @RunWith(RobolectricTestRunner.class) 56 public class BatteryEntryTest { 57 58 private static final int APP_UID = 123; 59 private static final int SYSTEM_UID = Process.SYSTEM_UID; 60 private static final String APP_DEFAULT_PACKAGE_NAME = "com.android.test"; 61 private static final String LABEL_PREFIX = "Label for "; 62 private static final String HIGH_DRAIN_PACKAGE = "com.android.test.screen"; 63 private static final String ANDROID_PACKAGE = "android"; 64 65 @Rule public MockitoRule mocks = MockitoJUnit.rule(); 66 67 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 68 private Context mMockContext; 69 private Context mContext; 70 @Mock private Handler mockHandler; 71 @Mock private PackageManager mockPackageManager; 72 @Mock private UserManager mockUserManager; 73 @Mock private UidBatteryConsumer mUidBatteryConsumer; 74 75 @Before stubContextToReturnMockPackageManager()76 public void stubContextToReturnMockPackageManager() { 77 mContext = spy(RuntimeEnvironment.application); 78 when(mMockContext.getPackageManager()).thenReturn(mockPackageManager); 79 } 80 81 @Before stubPackageManagerToReturnAppPackageAndName()82 public void stubPackageManagerToReturnAppPackageAndName() throws NameNotFoundException { 83 when(mockPackageManager.getApplicationInfo(anyString(), eq(0) /* no flags */)) 84 .thenAnswer(invocation -> { 85 ApplicationInfo info = new ApplicationInfo(); 86 info.packageName = invocation.getArgument(0); 87 return info; 88 }); 89 when(mockPackageManager.getApplicationLabel(any(ApplicationInfo.class))) 90 .thenAnswer(invocation -> LABEL_PREFIX 91 + ((ApplicationInfo) invocation.getArgument(0)).packageName); 92 } 93 createBatteryEntryForApp(String[] packages, String packageName, String highDrainPackage)94 private BatteryEntry createBatteryEntryForApp(String[] packages, String packageName, 95 String highDrainPackage) { 96 UidBatteryConsumer consumer = mock(UidBatteryConsumer.class); 97 when(consumer.getUid()).thenReturn(APP_UID); 98 when(consumer.getPackageWithHighestDrain()).thenReturn(highDrainPackage); 99 return new BatteryEntry(mMockContext, mockHandler, mockUserManager, 100 consumer, false, APP_UID, packages, packageName); 101 } 102 createAggregateBatteryEntry(int powerComponentId)103 private BatteryEntry createAggregateBatteryEntry(int powerComponentId) { 104 return new BatteryEntry(mMockContext, powerComponentId, 200, 100, 1000); 105 } 106 createCustomAggregateBatteryEntry(int powerComponentId)107 private BatteryEntry createCustomAggregateBatteryEntry(int powerComponentId) { 108 return new BatteryEntry(mMockContext, powerComponentId, "CUSTOM", 200, 100); 109 } 110 createUserBatteryConsumer(int userId)111 private BatteryEntry createUserBatteryConsumer(int userId) { 112 UserBatteryConsumer consumer = mock(UserBatteryConsumer.class); 113 when(consumer.getUserId()).thenReturn(userId); 114 return new BatteryEntry(mMockContext, mockHandler, mockUserManager, 115 consumer, false, 0, null, null); 116 } 117 118 @Test batteryEntryForApp_shouldSetDefaultPackageNameAndLabel()119 public void batteryEntryForApp_shouldSetDefaultPackageNameAndLabel() throws Exception { 120 BatteryEntry entry = createBatteryEntryForApp(null, APP_DEFAULT_PACKAGE_NAME, 121 HIGH_DRAIN_PACKAGE); 122 123 assertThat(entry.getDefaultPackageName()).isEqualTo(APP_DEFAULT_PACKAGE_NAME); 124 assertThat(entry.getLabel()).isEqualTo(LABEL_PREFIX + APP_DEFAULT_PACKAGE_NAME); 125 } 126 127 @Test batteryEntryForApp_shouldSetLabelAsPackageName_whenPackageCannotBeFound()128 public void batteryEntryForApp_shouldSetLabelAsPackageName_whenPackageCannotBeFound() 129 throws Exception { 130 when(mockPackageManager.getApplicationInfo(APP_DEFAULT_PACKAGE_NAME, 0 /* no flags */)) 131 .thenThrow(new NameNotFoundException()); 132 133 BatteryEntry entry = createBatteryEntryForApp(null, APP_DEFAULT_PACKAGE_NAME, null); 134 135 assertThat(entry.getLabel()).isEqualTo(APP_DEFAULT_PACKAGE_NAME); 136 } 137 138 @Test batteryEntryForApp_shouldSetHighestDrainPackage_whenPackagesCannotBeFoundForUid()139 public void batteryEntryForApp_shouldSetHighestDrainPackage_whenPackagesCannotBeFoundForUid() { 140 when(mockPackageManager.getPackagesForUid(APP_UID)).thenReturn(null); 141 142 BatteryEntry entry = createBatteryEntryForApp(null, null, HIGH_DRAIN_PACKAGE); 143 144 assertThat(entry.getLabel()).isEqualTo(LABEL_PREFIX + HIGH_DRAIN_PACKAGE); 145 } 146 147 @Test batteryEntryForApp_shouldSetHighestDrainPackage_whenMultiplePackagesFoundForUid()148 public void batteryEntryForApp_shouldSetHighestDrainPackage_whenMultiplePackagesFoundForUid() { 149 BatteryEntry entry = createBatteryEntryForApp( 150 new String[] {APP_DEFAULT_PACKAGE_NAME, "package2", "package3"}, null, 151 HIGH_DRAIN_PACKAGE); 152 153 assertThat(entry.getLabel()).isEqualTo(LABEL_PREFIX + HIGH_DRAIN_PACKAGE); 154 } 155 156 @Test batteryEntryForAOD_containCorrectInfo()157 public void batteryEntryForAOD_containCorrectInfo() { 158 final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, 159 BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY, 200, 100, 1000); 160 161 assertThat(entry.iconId).isEqualTo(R.drawable.ic_settings_aod); 162 assertThat(entry.name).isEqualTo("Ambient display"); 163 } 164 165 @Test batteryEntryForCustomComponent_containCorrectInfo()166 public void batteryEntryForCustomComponent_containCorrectInfo() { 167 final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, 168 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 42, "ABC", 200, 100); 169 170 assertThat(entry.iconId).isEqualTo(R.drawable.ic_power_system); 171 assertThat(entry.name).isEqualTo("ABC"); 172 } 173 174 @Test getTimeInForegroundMs_app()175 public void getTimeInForegroundMs_app() { 176 when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND)) 177 .thenReturn(100L); 178 179 final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler, 180 mockUserManager, mUidBatteryConsumer, false, 0, null, null); 181 182 assertThat(entry.getTimeInForegroundMs()).isEqualTo(100L); 183 } 184 185 @Test getTimeInForegroundMs_aggregateBatteryConsumer()186 public void getTimeInForegroundMs_aggregateBatteryConsumer() { 187 final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, 188 BatteryConsumer.POWER_COMPONENT_BLUETOOTH, 10, 20, 100); 189 190 assertThat(entry.getTimeInForegroundMs()).isEqualTo(100L); 191 } 192 193 @Test getTimeInBackgroundMs_app()194 public void getTimeInBackgroundMs_app() { 195 when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND)) 196 .thenReturn(100L); 197 198 final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler, 199 mockUserManager, mUidBatteryConsumer, false, 0, null, null); 200 201 assertThat(entry.getTimeInBackgroundMs()).isEqualTo(100L); 202 } 203 204 @Test getTimeInBackgroundMs_systemConsumer()205 public void getTimeInBackgroundMs_systemConsumer() { 206 final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, 207 BatteryConsumer.POWER_COMPONENT_BLUETOOTH, 100, 200, 1000); 208 209 assertThat(entry.getTimeInBackgroundMs()).isEqualTo(0); 210 } 211 212 @Test testUidCache_switchLocale_shouldCleanCache()213 public void testUidCache_switchLocale_shouldCleanCache() { 214 BatteryEntry.stopRequestQueue(); 215 216 Locale.setDefault(new Locale("en_US")); 217 BatteryEntry.sUidCache.put(Integer.toString(APP_UID), null); 218 assertThat(BatteryEntry.sUidCache).isNotEmpty(); 219 220 Locale.setDefault(new Locale("zh_TW")); 221 createBatteryEntryForApp(null, null, HIGH_DRAIN_PACKAGE); 222 assertThat(BatteryEntry.sUidCache).isEmpty(); // check if cache is clear 223 } 224 225 @Test getKey_UidBatteryConsumer()226 public void getKey_UidBatteryConsumer() { 227 final BatteryEntry entry = createBatteryEntryForApp(null, null, null); 228 final String key = entry.getKey(); 229 assertThat(key).isEqualTo("123"); 230 } 231 232 @Test getKey_AggregateBatteryConsumer_returnComponentId()233 public void getKey_AggregateBatteryConsumer_returnComponentId() { 234 final BatteryEntry entry = createAggregateBatteryEntry( 235 BatteryConsumer.POWER_COMPONENT_BLUETOOTH); 236 final String key = entry.getKey(); 237 assertThat(key).isEqualTo("S|2"); 238 } 239 240 @Test getKey_CustomAggregateBatteryConsumer_returnComponentId()241 public void getKey_CustomAggregateBatteryConsumer_returnComponentId() { 242 final BatteryEntry entry = createCustomAggregateBatteryEntry( 243 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 42); 244 final String key = entry.getKey(); 245 assertThat(key).isEqualTo("S|1042"); 246 } 247 248 @Test getKey_UserBatteryConsumer_returnUserId()249 public void getKey_UserBatteryConsumer_returnUserId() { 250 doReturn(mockUserManager).when(mMockContext).getSystemService(UserManager.class); 251 final BatteryEntry entry = createUserBatteryConsumer(2); 252 final String key = entry.getKey(); 253 assertThat(key).isEqualTo("U|2"); 254 } 255 256 @Test getNameAndIconFromUserId_nullUserInfo_returnDefaultNameAndIcon()257 public void getNameAndIconFromUserId_nullUserInfo_returnDefaultNameAndIcon() { 258 final int userId = 1001; 259 doReturn(mockUserManager).when(mContext).getSystemService(UserManager.class); 260 doReturn(null).when(mockUserManager).getUserInfo(userId); 261 262 final NameAndIcon nameAndIcon = BatteryEntry.getNameAndIconFromUserId( 263 mContext, userId); 264 assertThat(nameAndIcon.name).isEqualTo(getString( 265 R.string.running_process_item_removed_user_label)); 266 assertThat(nameAndIcon.icon).isNull(); 267 } 268 269 @Test getNameAndIconFromUid_rerturnExpectedName()270 public void getNameAndIconFromUid_rerturnExpectedName() { 271 final NameAndIcon nameAndIcon = BatteryEntry.getNameAndIconFromUid( 272 mContext, /* name */ null, /* uid */ 0); 273 assertThat(nameAndIcon.name).isEqualTo(getString(R.string.process_kernel_label)); 274 275 assertNameAndIcon("mediaserver", R.string.process_mediaserver_label); 276 assertNameAndIcon("dex2oat32", R.string.process_dex2oat_label); 277 assertNameAndIcon("dex2oat64", R.string.process_dex2oat_label); 278 assertNameAndIcon("dex2oat", R.string.process_dex2oat_label); 279 } 280 281 @Test getNameAndIconFromPowerComponent_rerturnExpectedNameAndIcon()282 public void getNameAndIconFromPowerComponent_rerturnExpectedNameAndIcon() { 283 assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY, 284 R.string.ambient_display_screen_title, 285 R.drawable.ic_settings_aod); 286 assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, 287 R.string.power_bluetooth, 288 com.android.internal.R.drawable.ic_settings_bluetooth); 289 assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_CAMERA, 290 R.string.power_camera, 291 R.drawable.ic_settings_camera); 292 assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, 293 R.string.power_cell, 294 R.drawable.ic_cellular_1_bar); 295 assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT, 296 R.string.power_flashlight, 297 R.drawable.ic_settings_display); 298 assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_PHONE, 299 R.string.power_phone, 300 R.drawable.ic_settings_voice_calls); 301 assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_SCREEN, 302 R.string.power_screen, 303 R.drawable.ic_settings_display); 304 assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_WIFI, 305 R.string.power_wifi, 306 R.drawable.ic_settings_wireless); 307 assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_IDLE, 308 R.string.power_idle, 309 R.drawable.ic_settings_phone_idle); 310 } 311 assertNameAndIcon(String name, int stringId)312 private void assertNameAndIcon(String name, int stringId) { 313 final NameAndIcon nameAndIcon = BatteryEntry.getNameAndIconFromUid( 314 mContext, name, /* uid */ 1000); 315 assertThat(nameAndIcon.name).isEqualTo(getString(stringId)); 316 } 317 assertNameAndIcon(int powerComponentId, int stringId, int iconId)318 private void assertNameAndIcon(int powerComponentId, int stringId, int iconId) { 319 final NameAndIcon nameAndIcon = BatteryEntry.getNameAndIconFromPowerComponent( 320 mContext, powerComponentId); 321 assertThat(nameAndIcon.name).isEqualTo(getString(stringId)); 322 assertThat(nameAndIcon.iconId).isEqualTo(iconId); 323 } 324 getString(int stringId)325 private String getString(int stringId) { 326 return mContext.getResources().getString(stringId); 327 } 328 } 329