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.Mockito.mock;
21 import static org.mockito.Mockito.when;
22 
23 import android.content.Context;
24 import android.content.pm.ApplicationInfo;
25 import android.content.pm.PackageManager;
26 import android.content.pm.PackageManager.NameNotFoundException;
27 import android.os.Handler;
28 import android.os.Process;
29 import android.os.UserManager;
30 
31 import com.android.internal.os.BatterySipper;
32 import com.android.internal.os.BatterySipper.DrainType;
33 import com.android.settings.R;
34 
35 import org.junit.Before;
36 import org.junit.Rule;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.mockito.Mock;
40 import org.mockito.junit.MockitoJUnit;
41 import org.mockito.junit.MockitoRule;
42 import org.robolectric.RobolectricTestRunner;
43 import org.robolectric.RuntimeEnvironment;
44 
45 import java.util.Locale;
46 
47 @RunWith(RobolectricTestRunner.class)
48 public class BatteryEntryTest {
49 
50     private static final int APP_UID = 123;
51     private static final int SYSTEM_UID = Process.SYSTEM_UID;
52     private static final String APP_DEFAULT_PACKAGE_NAME = "com.android.test";
53     private static final String APP_LABEL = "Test App Name";
54     private static final String HIGH_DRAIN_PACKAGE = "com.android.test.screen";
55     private static final String ANDROID_PACKAGE = "android";
56     private static final String[] SYSTEM_PACKAGES = {HIGH_DRAIN_PACKAGE, ANDROID_PACKAGE};
57 
58     @Rule public MockitoRule mocks = MockitoJUnit.rule();
59 
60     @Mock private Context mockContext;
61     @Mock private Handler mockHandler;
62     @Mock private PackageManager mockPackageManager;
63     @Mock private UserManager mockUserManager;
64 
65     @Before
stubContextToReturnMockPackageManager()66     public void stubContextToReturnMockPackageManager() {
67         when(mockContext.getPackageManager()).thenReturn(mockPackageManager);
68     }
69 
70     @Before
stubPackageManagerToReturnAppPackageAndName()71     public void stubPackageManagerToReturnAppPackageAndName() throws NameNotFoundException {
72         when(mockPackageManager.getPackagesForUid(APP_UID))
73             .thenReturn(new String[] {APP_DEFAULT_PACKAGE_NAME});
74 
75         ApplicationInfo appInfo = mock(ApplicationInfo.class);
76         when(mockPackageManager.getApplicationInfo(APP_DEFAULT_PACKAGE_NAME, 0 /* no flags */))
77             .thenReturn(appInfo);
78         when(mockPackageManager.getApplicationLabel(appInfo)).thenReturn(APP_LABEL);
79     }
80 
createBatteryEntryForApp()81     private BatteryEntry createBatteryEntryForApp() {
82         return new BatteryEntry(mockContext, mockHandler, mockUserManager, createSipperForApp());
83     }
84 
createSipperForApp()85     private BatterySipper createSipperForApp() {
86         BatterySipper sipper =
87             new BatterySipper(DrainType.APP, new FakeUid(APP_UID), 0 /* power use */);
88         sipper.packageWithHighestDrain = HIGH_DRAIN_PACKAGE;
89         return sipper;
90     }
91 
createBatteryEntryForSystem()92     private BatteryEntry createBatteryEntryForSystem() {
93         return new BatteryEntry(mockContext, mockHandler, mockUserManager, createSipperForSystem());
94     }
95 
createSipperForSystem()96     private BatterySipper createSipperForSystem() {
97         BatterySipper sipper =
98                 new BatterySipper(DrainType.APP, new FakeUid(SYSTEM_UID), 0 /* power use */);
99         sipper.packageWithHighestDrain = HIGH_DRAIN_PACKAGE;
100         sipper.mPackages = SYSTEM_PACKAGES;
101         return sipper;
102     }
103 
104     @Test
batteryEntryForApp_shouldSetDefaultPackageNameAndLabel()105     public void batteryEntryForApp_shouldSetDefaultPackageNameAndLabel() throws Exception {
106         BatteryEntry entry = createBatteryEntryForApp();
107 
108         assertThat(entry.defaultPackageName).isEqualTo(APP_DEFAULT_PACKAGE_NAME);
109         assertThat(entry.getLabel()).isEqualTo(APP_LABEL);
110     }
111 
112     @Test
batteryEntryForApp_shouldSetLabelAsPackageName_whenPackageCannotBeFound()113     public void batteryEntryForApp_shouldSetLabelAsPackageName_whenPackageCannotBeFound()
114         throws Exception {
115       when(mockPackageManager.getApplicationInfo(APP_DEFAULT_PACKAGE_NAME, 0 /* no flags */))
116           .thenThrow(new NameNotFoundException());
117 
118       BatteryEntry entry = createBatteryEntryForApp();
119 
120       assertThat(entry.getLabel()).isEqualTo(APP_DEFAULT_PACKAGE_NAME);
121     }
122 
123     @Test
batteryEntryForApp_shouldSetHighestDrainPackage_whenPackagesCannotBeFoundForUid()124     public void batteryEntryForApp_shouldSetHighestDrainPackage_whenPackagesCannotBeFoundForUid() {
125         when(mockPackageManager.getPackagesForUid(APP_UID)).thenReturn(null);
126 
127         BatteryEntry entry = createBatteryEntryForApp();
128 
129         assertThat(entry.getLabel()).isEqualTo(HIGH_DRAIN_PACKAGE);
130     }
131 
132     @Test
batteryEntryForApp_shouldSetHighestDrainPackage_whenMultiplePackagesFoundForUid()133     public void batteryEntryForApp_shouldSetHighestDrainPackage_whenMultiplePackagesFoundForUid() {
134         when(mockPackageManager.getPackagesForUid(APP_UID))
135             .thenReturn(new String[] {APP_DEFAULT_PACKAGE_NAME, "package2", "package3"});
136 
137         BatteryEntry entry = createBatteryEntryForApp();
138 
139         assertThat(entry.getLabel()).isEqualTo(HIGH_DRAIN_PACKAGE);
140     }
141 
142     @Test
batteryEntryForAOD_containCorrectInfo()143     public void batteryEntryForAOD_containCorrectInfo() {
144         final BatterySipper batterySipper = mock(BatterySipper.class);
145         batterySipper.drainType = DrainType.AMBIENT_DISPLAY;
146         final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
147                 mockUserManager, batterySipper);
148 
149         assertThat(entry.iconId).isEqualTo(R.drawable.ic_settings_aod);
150         assertThat(entry.name).isEqualTo("Ambient display");
151     }
152 
153     @Test
extractPackageFromSipper_systemSipper_returnSystemPackage()154     public void extractPackageFromSipper_systemSipper_returnSystemPackage() {
155         BatteryEntry entry = createBatteryEntryForSystem();
156 
157         assertThat(entry.extractPackagesFromSipper(entry.sipper))
158             .isEqualTo(new String[] {ANDROID_PACKAGE});
159     }
160 
161     @Test
extractPackageFromSipper_normalSipper_returnDefaultPackage()162     public void extractPackageFromSipper_normalSipper_returnDefaultPackage() {
163         BatteryEntry entry = createBatteryEntryForApp();
164 
165         assertThat(entry.extractPackagesFromSipper(entry.sipper)).isEqualTo(entry.sipper.mPackages);
166     }
167 
168     @Test
testUidCache_switchLocale_shouldCleanCache()169     public void testUidCache_switchLocale_shouldCleanCache() {
170         BatteryEntry.stopRequestQueue();
171 
172         Locale.setDefault(new Locale("en_US"));
173         BatteryEntry.sUidCache.put(Integer.toString(APP_UID), null);
174         assertThat(BatteryEntry.sUidCache).isNotEmpty();
175 
176         Locale.setDefault(new Locale("zh_TW"));
177         createBatteryEntryForApp();
178         assertThat(BatteryEntry.sUidCache).isEmpty(); // check if cache is clear
179     }
180 }
181