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; 18 19 import static com.google.common.truth.Truth.assertThat; 20 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.anyString; 25 import static org.mockito.Matchers.eq; 26 import static org.mockito.Mockito.doAnswer; 27 import static org.mockito.Mockito.doReturn; 28 import static org.mockito.Mockito.mock; 29 import static org.mockito.Mockito.spy; 30 import static org.mockito.Mockito.verify; 31 import static org.mockito.Mockito.when; 32 33 import android.app.Activity; 34 import android.app.Fragment; 35 import android.content.Context; 36 import android.content.pm.ApplicationInfo; 37 import android.content.pm.PackageManager; 38 import android.graphics.drawable.Drawable; 39 import android.os.BatteryStats; 40 import android.os.Bundle; 41 import android.os.UserHandle; 42 import android.view.View; 43 44 import com.android.internal.os.BatterySipper; 45 import com.android.internal.os.BatteryStatsHelper; 46 import com.android.settings.SettingsActivity; 47 import com.android.settings.SettingsRobolectricTestRunner; 48 import com.android.settings.TestConfig; 49 import com.android.settings.applications.AppHeaderController; 50 import com.android.settings.applications.LayoutPreference; 51 import com.android.settings.testutils.FakeFeatureFactory; 52 import com.android.settingslib.applications.AppUtils; 53 import com.android.settingslib.applications.ApplicationsState; 54 import com.android.settingslib.applications.instantapps.InstantAppDataProvider; 55 56 import org.junit.Before; 57 import org.junit.Test; 58 import org.junit.runner.RunWith; 59 import org.mockito.Answers; 60 import org.mockito.ArgumentCaptor; 61 import org.mockito.Mock; 62 import org.mockito.MockitoAnnotations; 63 import org.mockito.invocation.InvocationOnMock; 64 import org.mockito.stubbing.Answer; 65 import org.robolectric.RuntimeEnvironment; 66 import org.robolectric.annotation.Config; 67 import org.robolectric.annotation.Implementation; 68 import org.robolectric.annotation.Implements; 69 import org.robolectric.util.ReflectionHelpers; 70 71 @RunWith(SettingsRobolectricTestRunner.class) 72 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) 73 public class AdvancedPowerUsageDetailTest { 74 private static final String APP_LABEL = "app label"; 75 private static final String SUMMARY = "summary"; 76 private static final String[] PACKAGE_NAME = {"com.android.app"}; 77 private static final String USAGE_PERCENT = "16"; 78 private static final int ICON_ID = 123; 79 private static final int UID = 1; 80 private static final long BACKGROUND_TIME_US = 100 * 1000; 81 private static final long FOREGROUND_TIME_US = 200 * 1000; 82 private static final long BACKGROUND_TIME_MS = 100; 83 private static final long FOREGROUND_TIME_MS = 200; 84 private static final long PHONE_FOREGROUND_TIME_MS = 250 * 1000; 85 private static final long PHONE_BACKGROUND_TIME_MS = 0; 86 87 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 88 private Context mContext; 89 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 90 private Activity mActivity; 91 @Mock 92 private AppHeaderController mAppHeaderController; 93 @Mock 94 private LayoutPreference mHeaderPreference; 95 @Mock 96 private ApplicationsState mState; 97 @Mock 98 private ApplicationsState.AppEntry mAppEntry; 99 @Mock 100 private Bundle mBundle; 101 @Mock 102 private BatteryEntry mBatteryEntry; 103 @Mock 104 private BatterySipper mBatterySipper; 105 @Mock 106 private BatteryStatsHelper mBatteryStatsHelper; 107 @Mock 108 private BatteryStats.Uid mUid; 109 @Mock 110 private PackageManager mPackageManager; 111 private AdvancedPowerUsageDetail mFragment; 112 private FakeFeatureFactory mFeatureFactory; 113 private SettingsActivity mTestActivity; 114 115 @Before setUp()116 public void setUp() { 117 MockitoAnnotations.initMocks(this); 118 FakeFeatureFactory.setupForTest(mContext); 119 mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); 120 121 mFragment = spy(new AdvancedPowerUsageDetail()); 122 doReturn(mContext).when(mFragment).getContext(); 123 doReturn(mActivity).when(mFragment).getActivity(); 124 doReturn(SUMMARY).when(mFragment).getString(anyInt()); 125 doReturn(APP_LABEL).when(mBundle).getString(anyString()); 126 doReturn(mBundle).when(mFragment).getArguments(); 127 128 doReturn(mAppHeaderController).when(mFeatureFactory.applicationFeatureProvider) 129 .newAppHeaderController(any(Fragment.class), any(View.class)); 130 doReturn(mAppHeaderController).when(mAppHeaderController).setButtonActions(anyInt(), 131 anyInt()); 132 doReturn(mAppHeaderController).when(mAppHeaderController).setIcon(any(Drawable.class)); 133 doReturn(mAppHeaderController).when(mAppHeaderController).setIcon(any( 134 ApplicationsState.AppEntry.class)); 135 doReturn(mAppHeaderController).when(mAppHeaderController).setLabel(anyString()); 136 doReturn(mAppHeaderController).when(mAppHeaderController).setLabel(any( 137 ApplicationsState.AppEntry.class)); 138 doReturn(mAppHeaderController).when(mAppHeaderController).setSummary(anyString()); 139 140 141 doReturn(UID).when(mBatterySipper).getUid(); 142 doReturn(APP_LABEL).when(mBatteryEntry).getLabel(); 143 doReturn(BACKGROUND_TIME_US).when(mUid).getProcessStateTime( 144 eq(BatteryStats.Uid.PROCESS_STATE_BACKGROUND), anyLong(), anyInt()); 145 doReturn(FOREGROUND_TIME_US).when(mUid).getProcessStateTime( 146 eq(BatteryStats.Uid.PROCESS_STATE_TOP), anyLong(), anyInt()); 147 ReflectionHelpers.setField(mBatteryEntry, "sipper", mBatterySipper); 148 mBatteryEntry.iconId = ICON_ID; 149 mBatterySipper.uidObj = mUid; 150 mBatterySipper.drainType = BatterySipper.DrainType.APP; 151 152 mFragment.mHeaderPreference = mHeaderPreference; 153 mFragment.mState = mState; 154 mFragment.mBatteryUtils = new BatteryUtils(RuntimeEnvironment.application); 155 mAppEntry.info = mock(ApplicationInfo.class); 156 157 mTestActivity = spy(new SettingsActivity()); 158 doReturn(mPackageManager).when(mTestActivity).getPackageManager(); 159 160 final ArgumentCaptor<Bundle> captor = ArgumentCaptor.forClass(Bundle.class); 161 162 Answer<Void> callable = new Answer<Void>() { 163 @Override 164 public Void answer(InvocationOnMock invocation) throws Exception { 165 mBundle = captor.getValue(); 166 return null; 167 } 168 }; 169 doAnswer(callable).when(mTestActivity).startPreferencePanelAsUser(any(), anyString(), 170 captor.capture(), anyInt(), any(), any()); 171 } 172 173 @Test testInitHeader_NoAppEntry_BuildByBundle()174 public void testInitHeader_NoAppEntry_BuildByBundle() { 175 mFragment.mAppEntry = null; 176 mFragment.initHeader(); 177 178 verify(mAppHeaderController).setIcon(any(Drawable.class)); 179 verify(mAppHeaderController).setLabel(APP_LABEL); 180 } 181 182 @Test testInitHeader_HasAppEntry_BuildByAppEntry()183 public void testInitHeader_HasAppEntry_BuildByAppEntry() { 184 ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", 185 new InstantAppDataProvider() { 186 @Override 187 public boolean isInstantApp(ApplicationInfo info) { 188 return false; 189 } 190 }); 191 mFragment.mAppEntry = mAppEntry; 192 mFragment.initHeader(); 193 194 verify(mAppHeaderController).setIcon(mAppEntry); 195 verify(mAppHeaderController).setLabel(mAppEntry); 196 verify(mAppHeaderController).setIsInstantApp(false); 197 } 198 199 @Test testInitHeader_HasAppEntry_InstantApp()200 public void testInitHeader_HasAppEntry_InstantApp() { 201 ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", 202 new InstantAppDataProvider() { 203 @Override 204 public boolean isInstantApp(ApplicationInfo info) { 205 return true; 206 } 207 }); 208 mFragment.mAppEntry = mAppEntry; 209 mFragment.initHeader(); 210 211 verify(mAppHeaderController).setIcon(mAppEntry); 212 verify(mAppHeaderController).setLabel(mAppEntry); 213 verify(mAppHeaderController).setIsInstantApp(true); 214 verify(mAppHeaderController).setSummary((CharSequence) null); 215 } 216 217 @Test testStartBatteryDetailPage_hasBasicData()218 public void testStartBatteryDetailPage_hasBasicData() { 219 AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0, 220 mBatteryEntry, USAGE_PERCENT); 221 222 assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID); 223 assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME)).isEqualTo( 224 BACKGROUND_TIME_MS); 225 assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME)).isEqualTo( 226 FOREGROUND_TIME_MS); 227 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT)).isEqualTo( 228 USAGE_PERCENT); 229 } 230 231 @Test testStartBatteryDetailPage_typeNotApp_hasBasicData()232 public void testStartBatteryDetailPage_typeNotApp_hasBasicData() { 233 mBatterySipper.drainType = BatterySipper.DrainType.PHONE; 234 mBatterySipper.usageTimeMs = PHONE_FOREGROUND_TIME_MS; 235 236 AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0, 237 mBatteryEntry, USAGE_PERCENT); 238 239 assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_UID)).isEqualTo(UID); 240 assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME)).isEqualTo( 241 PHONE_FOREGROUND_TIME_MS); 242 assertThat(mBundle.getLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME)).isEqualTo( 243 PHONE_BACKGROUND_TIME_MS); 244 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT)).isEqualTo( 245 USAGE_PERCENT); 246 } 247 248 @Test testStartBatteryDetailPage_NormalApp()249 public void testStartBatteryDetailPage_NormalApp() { 250 mBatterySipper.mPackages = PACKAGE_NAME; 251 mBatteryEntry.defaultPackageName = PACKAGE_NAME[0]; 252 AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0, 253 mBatteryEntry, USAGE_PERCENT); 254 255 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isEqualTo( 256 PACKAGE_NAME[0]); 257 } 258 259 @Test testStartBatteryDetailPage_SystemApp()260 public void testStartBatteryDetailPage_SystemApp() { 261 mBatterySipper.mPackages = null; 262 AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0, 263 mBatteryEntry, USAGE_PERCENT); 264 265 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_LABEL)).isEqualTo(APP_LABEL); 266 assertThat(mBundle.getInt(AdvancedPowerUsageDetail.EXTRA_ICON_ID)).isEqualTo(ICON_ID); 267 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isEqualTo(null); 268 } 269 270 @Test testStartBatteryDetailPage_WorkApp()271 public void testStartBatteryDetailPage_WorkApp() { 272 final int appUid = 1010019; 273 mBatterySipper.mPackages = PACKAGE_NAME; 274 doReturn(appUid).when(mBatterySipper).getUid(); 275 AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, mBatteryStatsHelper, 0, 276 mBatteryEntry, USAGE_PERCENT); 277 278 verify(mTestActivity).startPreferencePanelAsUser( 279 any(), anyString(), any(), anyInt(), any(), eq(new UserHandle(10))); 280 } 281 282 @Test testStartBatteryDetailPage_noBatteryUsage_hasBasicData()283 public void testStartBatteryDetailPage_noBatteryUsage_hasBasicData() { 284 final ArgumentCaptor<Bundle> captor = ArgumentCaptor.forClass(Bundle.class); 285 Answer<Void> callable = new Answer<Void>() { 286 @Override 287 public Void answer(InvocationOnMock invocation) throws Exception { 288 mBundle = captor.getValue(); 289 return null; 290 } 291 }; 292 doAnswer(callable).when(mTestActivity).startPreferencePanelAsUser(any(), anyString(), 293 captor.capture(), anyInt(), any(), any()); 294 295 AdvancedPowerUsageDetail.startBatteryDetailPage(mTestActivity, null, PACKAGE_NAME[0]); 296 297 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME)).isEqualTo( 298 PACKAGE_NAME[0]); 299 assertThat(mBundle.getString(AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT)).isEqualTo( 300 "0%"); 301 } 302 } 303