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.applications.appinfo;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.anyDouble;
22 import static org.mockito.ArgumentMatchers.anyInt;
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.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.app.AppOpsManager;
30 import android.content.Context;
31 import android.content.pm.PackageManager;
32 import android.content.pm.PackageManager.NameNotFoundException;
33 import android.os.BatteryUsageStats;
34 import android.os.Bundle;
35 import android.os.UidBatteryConsumer;
36 
37 import androidx.loader.app.LoaderManager;
38 import androidx.preference.Preference;
39 import androidx.preference.PreferenceScreen;
40 
41 import com.android.settings.SettingsActivity;
42 import com.android.settings.fuelgauge.BatteryDiffEntry;
43 import com.android.settings.fuelgauge.BatteryUtils;
44 
45 import org.junit.Before;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.mockito.Mock;
49 import org.mockito.MockitoAnnotations;
50 import org.robolectric.RobolectricTestRunner;
51 import org.robolectric.RuntimeEnvironment;
52 import org.robolectric.annotation.Config;
53 
54 import java.util.ArrayList;
55 import java.util.List;
56 
57 @RunWith(RobolectricTestRunner.class)
58 public class AppBatteryPreferenceControllerTest {
59 
60     private static final int TARGET_UID = 111;
61     private static final int OTHER_UID = 222;
62     private static final double BATTERY_LEVEL = 60;
63 
64     @Mock
65     private SettingsActivity mActivity;
66     @Mock
67     private BatteryUtils mBatteryUtils;
68     @Mock
69     private BatteryUsageStats mBatteryUsageStats;
70     @Mock
71     private UidBatteryConsumer mUidBatteryConsumer;
72     @Mock
73     private UidBatteryConsumer mOtherUidBatteryConsumer;
74     @Mock
75     private PreferenceScreen mScreen;
76     @Mock
77     private PackageManager mPackageManager;
78     @Mock
79     private LoaderManager mLoaderManager;
80     @Mock
81     private BatteryDiffEntry mBatteryDiffEntry;
82 
83     private Context mContext;
84     private AppInfoDashboardFragment mFragment;
85     private AppBatteryPreferenceController mController;
86     private Preference mBatteryPreference;
87 
88     @Before
setUp()89     public void setUp() throws NameNotFoundException {
90         MockitoAnnotations.initMocks(this);
91         mContext = spy(RuntimeEnvironment.application);
92         when(mContext.getPackageManager()).thenReturn(mPackageManager);
93 
94         mFragment = spy(new AppInfoDashboardFragment());
95 
96         mBatteryPreference = spy(new Preference(RuntimeEnvironment.application));
97 
98         when(mUidBatteryConsumer.getUid()).thenReturn(TARGET_UID);
99         when(mOtherUidBatteryConsumer.getUid()).thenReturn(OTHER_UID);
100 
101         mController = spy(new AppBatteryPreferenceController(
102                 RuntimeEnvironment.application,
103                 mFragment,
104                 "package1" /* packageName */,
105                 0 /* uId */,
106                 null /* lifecycle */));
107         mController.mBatteryUtils = mBatteryUtils;
108         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mBatteryPreference);
109     }
110 
111     @Test
testAppBattery_byDefault_shouldBeShown()112     public void testAppBattery_byDefault_shouldBeShown() {
113         assertThat(mController.isAvailable()).isTrue();
114     }
115 
116     @Test
117     @Config(qualifiers = "mcc999")
testAppBattery_ifDisabled_shouldNotBeShown()118     public void testAppBattery_ifDisabled_shouldNotBeShown() {
119         assertThat(mController.isAvailable()).isFalse();
120     }
121 
122     @Test
findTargetBatteryConsumer_findCorrectBatteryConsumer()123     public void findTargetBatteryConsumer_findCorrectBatteryConsumer() {
124         final List<UidBatteryConsumer> uidBatteryConsumers = new ArrayList<>();
125         uidBatteryConsumers.add(mUidBatteryConsumer);
126         uidBatteryConsumers.add(mOtherUidBatteryConsumer);
127         when(mBatteryUsageStats.getUidBatteryConsumers()).thenReturn(uidBatteryConsumers);
128 
129         assertThat(mController.findTargetUidBatteryConsumer(mBatteryUsageStats, TARGET_UID))
130             .isEqualTo(mUidBatteryConsumer);
131     }
132 
133     @Test
updateBattery_noBatteryStats_summaryNo()134     public void updateBattery_noBatteryStats_summaryNo() {
135         mController.displayPreference(mScreen);
136 
137         mController.updateBattery();
138 
139         assertThat(mBatteryPreference.getSummary())
140             .isEqualTo("No battery use since last full charge");
141     }
142 
143     @Test
updateBattery_hasBatteryStats_summaryPercent()144     public void updateBattery_hasBatteryStats_summaryPercent() {
145         mController.mBatteryUsageStats = mBatteryUsageStats;
146         mController.mUidBatteryConsumer = mUidBatteryConsumer;
147         doReturn(BATTERY_LEVEL).when(mBatteryUtils).calculateBatteryPercent(anyDouble(),
148                 anyDouble(), anyInt());
149         mController.displayPreference(mScreen);
150 
151         mController.updateBattery();
152 
153         assertThat(mBatteryPreference.getSummary()).isEqualTo("60% use since last full charge");
154     }
155 
156     @Test
updateBatteryWithDiffEntry_noConsumePower_summaryNo()157     public void updateBatteryWithDiffEntry_noConsumePower_summaryNo() {
158         mController.displayPreference(mScreen);
159         mController.mIsChartGraphEnabled = true;
160 
161         mController.updateBatteryWithDiffEntry();
162 
163         assertThat(mBatteryPreference.getSummary()).isEqualTo("No battery use for past 24 hours");
164     }
165 
166     @Test
updateBatteryWithDiffEntry_withConsumePower_summaryPercent()167     public void updateBatteryWithDiffEntry_withConsumePower_summaryPercent() {
168         mController.displayPreference(mScreen);
169         mController.mIsChartGraphEnabled = true;
170         mBatteryDiffEntry.mConsumePower = 1;
171         mController.mBatteryDiffEntry = mBatteryDiffEntry;
172         when(mBatteryDiffEntry.getPercentOfTotal()).thenReturn(60.0);
173 
174         mController.updateBatteryWithDiffEntry();
175 
176         assertThat(mBatteryPreference.getSummary()).isEqualTo("60% use for past 24 hours");
177     }
178 
179     @Test
isBatteryStatsAvailable_hasBatteryStatsHelperAndSipper_returnTrue()180     public void isBatteryStatsAvailable_hasBatteryStatsHelperAndSipper_returnTrue() {
181         mController.mBatteryUsageStats = mBatteryUsageStats;
182         mController.mUidBatteryConsumer = mUidBatteryConsumer;
183 
184         assertThat(mController.isBatteryStatsAvailable()).isTrue();
185     }
186 
187     @Test
isBatteryStatsAvailable_parametersNull_returnFalse()188     public void isBatteryStatsAvailable_parametersNull_returnFalse() {
189         assertThat(mController.isBatteryStatsAvailable()).isFalse();
190     }
191 
192     @Test
launchPowerUsageDetailFragment_shouldNotCrash()193     public void launchPowerUsageDetailFragment_shouldNotCrash() {
194         when(mActivity.getSystemService(Context.APP_OPS_SERVICE))
195                 .thenReturn(mock(AppOpsManager.class));
196         when(mFragment.getActivity()).thenReturn(mActivity);
197         final String key = mController.getPreferenceKey();
198         when(mBatteryPreference.getKey()).thenReturn(key);
199         mController.mBatteryUsageStats = mBatteryUsageStats;
200         mController.mUidBatteryConsumer = mUidBatteryConsumer;
201 
202         // Should not crash
203         mController.handlePreferenceTreeClick(mBatteryPreference);
204     }
205 
206     @Test
onResume_shouldRestartBatteryStatsLoader()207     public void onResume_shouldRestartBatteryStatsLoader() {
208         doReturn(mLoaderManager).when(mFragment).getLoaderManager();
209 
210         mController.onResume();
211 
212         verify(mLoaderManager)
213                 .restartLoader(AppInfoDashboardFragment.LOADER_BATTERY_USAGE_STATS, Bundle.EMPTY,
214                         mController.mBatteryUsageStatsLoaderCallbacks);
215     }
216 
217     @Test
onPause_shouldDestroyBatteryStatsLoader()218     public void onPause_shouldDestroyBatteryStatsLoader() {
219         doReturn(mLoaderManager).when(mFragment).getLoaderManager();
220 
221         mController.onPause();
222 
223         verify(mLoaderManager).destroyLoader(AppInfoDashboardFragment.LOADER_BATTERY_USAGE_STATS);
224     }
225 }
226