1 /*
2  * Copyright (C) 2023 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 org.mockito.ArgumentMatchers.anyString;
20 import static org.mockito.Mockito.doReturn;
21 import static org.mockito.Mockito.never;
22 import static org.mockito.Mockito.spy;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.verify;
25 
26 import android.content.Context;
27 
28 import androidx.preference.Preference;
29 import androidx.preference.PreferenceCategory;
30 
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.mockito.Mock;
35 import org.mockito.MockitoAnnotations;
36 import org.robolectric.RobolectricTestRunner;
37 import org.robolectric.RuntimeEnvironment;
38 
39 @RunWith(RobolectricTestRunner.class)
40 public final class PowerUsageTimeControllerTest {
41     private static final String SLOT_TIME = "12 am-2 am";
42     private static final String KEY_SCREEN_ON_TIME_PREF = "battery_usage_screen_time";
43     private static final String KEY_BACKGROUND_TIME_PREF = "battery_usage_background_time";
44     private static final String TEST_ANOMALY_HINT_TEXT = "test_anomaly_hint_text";
45 
46     private Context mContext;
47     private PowerUsageTimeController mPowerUsageTimeController;
48 
49     @Mock private PreferenceCategory mPowerUsageTimeCategory;
50     @Mock private PowerUsageTimePreference mScreenTimePreference;
51     @Mock private PowerUsageTimePreference mBackgroundTimePreference;
52 
53     @Before
setUp()54     public void setUp() {
55         MockitoAnnotations.initMocks(this);
56         mContext = spy(RuntimeEnvironment.application);
57         mPowerUsageTimeController = new PowerUsageTimeController(mContext);
58         mPowerUsageTimeController.mPowerUsageTimeCategory = mPowerUsageTimeCategory;
59         mPowerUsageTimeController.mScreenTimePreference = mScreenTimePreference;
60         mPowerUsageTimeController.mBackgroundTimePreference = mBackgroundTimePreference;
61         doReturn(KEY_SCREEN_ON_TIME_PREF).when(mScreenTimePreference).getKey();
62         doReturn(KEY_BACKGROUND_TIME_PREF).when(mBackgroundTimePreference).getKey();
63     }
64 
65     @Test
handleScreenTimeUpdated_noInfo_prefInvisible()66     public void handleScreenTimeUpdated_noInfo_prefInvisible() {
67         mPowerUsageTimeController.handleScreenTimeUpdated(
68                 /* slotTime= */ null,
69                 /* screenOnTimeInMs= */ 0,
70                 /* backgroundTimeInMs= */ 0,
71                 /* anomalyHintPrefKey= */ null,
72                 /* anomalyHintText= */ null);
73 
74         verifyAllPreferencesVisible(false);
75     }
76 
77     @Test
handleScreenTimeUpdated_onlySlotTime_prefInvisible()78     public void handleScreenTimeUpdated_onlySlotTime_prefInvisible() {
79         mPowerUsageTimeController.handleScreenTimeUpdated(
80                 SLOT_TIME,
81                 /* screenOnTimeInMs= */ 0,
82                 /* backgroundTimeInMs= */ 0,
83                 /* anomalyHintPrefKey= */ null,
84                 /* anomalyHintText= */ null);
85 
86         verifyAllPreferencesVisible(false);
87     }
88 
89     @Test
handleScreenTimeUpdated_lackBackgroundTime_onlyScreenOnTime()90     public void handleScreenTimeUpdated_lackBackgroundTime_onlyScreenOnTime() {
91         final long screenOnTimeAMinute = 60000;
92         final long backgroundTimeZero = 0;
93 
94         mPowerUsageTimeController.handleScreenTimeUpdated(
95                 SLOT_TIME,
96                 screenOnTimeAMinute,
97                 backgroundTimeZero,
98                 /* anomalyHintPrefKey= */ null,
99                 /* anomalyHintText= */ null);
100 
101         verifyOnePreferenceInvisible(mBackgroundTimePreference);
102         verify(mScreenTimePreference).setTimeTitle("Screen time");
103         verify(mScreenTimePreference).setTimeSummary("1 min");
104         verify(mScreenTimePreference, never()).setAnomalyHint(anyString());
105     }
106 
107     @Test
handleScreenTimeUpdated_lackScreenOnTime_onlyBackgroundTime()108     public void handleScreenTimeUpdated_lackScreenOnTime_onlyBackgroundTime() {
109         final long screenOnTimeZero = 0;
110         final long backgroundTimeTwoMinutes = 120000;
111 
112         mPowerUsageTimeController.handleScreenTimeUpdated(
113                 SLOT_TIME,
114                 screenOnTimeZero,
115                 backgroundTimeTwoMinutes,
116                 /* anomalyHintPrefKey= */ null,
117                 /* anomalyHintText= */ null);
118 
119         verifyOnePreferenceInvisible(mScreenTimePreference);
120         verify(mBackgroundTimePreference).setTimeTitle("Background time");
121         verify(mBackgroundTimePreference).setTimeSummary("2 min");
122         verify(mBackgroundTimePreference, never()).setAnomalyHint(anyString());
123     }
124 
125     @Test
handleScreenTimeUpdated_categoryTitleWithSlotTime_expectedResult()126     public void handleScreenTimeUpdated_categoryTitleWithSlotTime_expectedResult() {
127         final long screenOnTimeAMinute = 60000;
128         final long backgroundTimeTwoMinutes = 120000;
129 
130         mPowerUsageTimeController.handleScreenTimeUpdated(
131                 SLOT_TIME,
132                 screenOnTimeAMinute,
133                 backgroundTimeTwoMinutes,
134                 /* anomalyHintPrefKey= */ null,
135                 /* anomalyHintText= */ null);
136 
137         verifyAllPreferencesVisible(true);
138         verify(mScreenTimePreference).setTimeTitle("Screen time");
139         verify(mScreenTimePreference).setTimeSummary("1 min");
140         verify(mScreenTimePreference, never()).setAnomalyHint(anyString());
141         verify(mBackgroundTimePreference).setTimeTitle("Background time");
142         verify(mBackgroundTimePreference).setTimeSummary("2 min");
143         verify(mBackgroundTimePreference, never()).setAnomalyHint(anyString());
144         verify(mPowerUsageTimeCategory).setTitle("App usage for 12 am-2 am");
145     }
146 
147     @Test
handleScreenTimeUpdated_categoryTitleWithoutSlotTime_expectedResult()148     public void handleScreenTimeUpdated_categoryTitleWithoutSlotTime_expectedResult() {
149         final long backgroundTimeTwoMinutes = 120000;
150         final long screenOnTimeAMinute = 60000;
151 
152         mPowerUsageTimeController.handleScreenTimeUpdated(
153                 /* slotTime= */ null,
154                 screenOnTimeAMinute,
155                 backgroundTimeTwoMinutes,
156                 /* anomalyHintPrefKey= */ null,
157                 /* anomalyHintText= */ null);
158 
159         verifyAllPreferencesVisible(true);
160         verify(mPowerUsageTimeCategory).setTitle("App usage since last full charge");
161     }
162 
163     @Test
handleScreenTimeUpdated_BackgroundLessThanAMinWithSlotTime_expectedResult()164     public void handleScreenTimeUpdated_BackgroundLessThanAMinWithSlotTime_expectedResult() {
165         final long screenOnTimeAMinute = 60000;
166         final long backgroundTimeLessThanAMinute = 59999;
167 
168         mPowerUsageTimeController.handleScreenTimeUpdated(
169                 SLOT_TIME,
170                 screenOnTimeAMinute,
171                 backgroundTimeLessThanAMinute,
172                 /* anomalyHintPrefKey= */ null,
173                 /* anomalyHintText= */ null);
174 
175         verifyAllPreferencesVisible(true);
176         verify(mScreenTimePreference).setTimeSummary("1 min");
177         verify(mBackgroundTimePreference).setTimeSummary("Less than a minute");
178     }
179 
180     @Test
handleScreenTimeUpdated_ScreenTimeLessThanAMin_expectedResult()181     public void handleScreenTimeUpdated_ScreenTimeLessThanAMin_expectedResult() {
182         final long screenOnTimeLessThanAMinute = 59999;
183         final long backgroundTimeTwoMinutes = 120000;
184 
185         mPowerUsageTimeController.handleScreenTimeUpdated(
186                 SLOT_TIME,
187                 screenOnTimeLessThanAMinute,
188                 backgroundTimeTwoMinutes,
189                 /* anomalyHintPrefKey= */ null,
190                 /* anomalyHintText= */ null);
191 
192         verifyAllPreferencesVisible(true);
193         verify(mScreenTimePreference).setTimeSummary("Less than a minute");
194         verify(mBackgroundTimePreference).setTimeSummary("2 min");
195     }
196 
197     @Test
handleScreenTimeUpdated_bothLessThanAMin_expectedResult()198     public void handleScreenTimeUpdated_bothLessThanAMin_expectedResult() {
199         final long screenOnTimeLessThanAMinute = 59999;
200         final long backgroundTimeLessThanAMinute = 59999;
201 
202         mPowerUsageTimeController.handleScreenTimeUpdated(
203                 SLOT_TIME,
204                 screenOnTimeLessThanAMinute,
205                 backgroundTimeLessThanAMinute,
206                 /* anomalyHintPrefKey= */ null,
207                 /* anomalyHintText= */ null);
208 
209         verifyAllPreferencesVisible(true);
210         verify(mScreenTimePreference).setTimeSummary("Less than a minute");
211         verify(mBackgroundTimePreference).setTimeSummary("Less than a minute");
212     }
213 
214     @Test
handleScreenTimeUpdated_anomalyOfScreenOnTime_expectedResult()215     public void handleScreenTimeUpdated_anomalyOfScreenOnTime_expectedResult() {
216         final long screenOnTimeAMinute = 60000;
217         final long backgroundTimeTwoMinutes = 120000;
218 
219         mPowerUsageTimeController.handleScreenTimeUpdated(
220                 SLOT_TIME,
221                 screenOnTimeAMinute,
222                 backgroundTimeTwoMinutes,
223                 KEY_SCREEN_ON_TIME_PREF,
224                 TEST_ANOMALY_HINT_TEXT);
225 
226         verifyAllPreferencesVisible(true);
227         verify(mScreenTimePreference).setAnomalyHint(TEST_ANOMALY_HINT_TEXT);
228         verify(mBackgroundTimePreference, never()).setAnomalyHint(anyString());
229     }
230 
231     @Test
handleScreenTimeUpdated_anomalyOfBackgroundTime_expectedResult()232     public void handleScreenTimeUpdated_anomalyOfBackgroundTime_expectedResult() {
233         final long screenOnTimeAMinute = 60000;
234         final long backgroundTimeTwoMinutes = 120000;
235 
236         mPowerUsageTimeController.handleScreenTimeUpdated(
237                 SLOT_TIME,
238                 screenOnTimeAMinute,
239                 backgroundTimeTwoMinutes,
240                 KEY_BACKGROUND_TIME_PREF,
241                 TEST_ANOMALY_HINT_TEXT);
242 
243         verifyAllPreferencesVisible(true);
244         verify(mScreenTimePreference, never()).setAnomalyHint(anyString());
245         verify(mBackgroundTimePreference).setAnomalyHint(TEST_ANOMALY_HINT_TEXT);
246     }
247 
248     @Test
handleScreenTimeUpdated_anomalyOfScreenOnTimeWithoutTimeInfo_expectedResult()249     public void handleScreenTimeUpdated_anomalyOfScreenOnTimeWithoutTimeInfo_expectedResult() {
250         final long screenOnTimeZero = 0;
251         final long backgroundTimeTwoMinutes = 120000;
252 
253         mPowerUsageTimeController.handleScreenTimeUpdated(
254                 SLOT_TIME,
255                 screenOnTimeZero,
256                 backgroundTimeTwoMinutes,
257                 KEY_SCREEN_ON_TIME_PREF,
258                 TEST_ANOMALY_HINT_TEXT);
259 
260         verifyAllPreferencesVisible(true);
261         verify(mScreenTimePreference).setTimeSummary("Less than a minute");
262         verify(mScreenTimePreference).setAnomalyHint(TEST_ANOMALY_HINT_TEXT);
263         verify(mBackgroundTimePreference, never()).setAnomalyHint(anyString());
264     }
265 
verifySetPrefToVisible(Preference pref, boolean isVisible)266     private void verifySetPrefToVisible(Preference pref, boolean isVisible) {
267         verify(pref, isVisible ? times(1) : never()).setVisible(true);
268     }
269 
verifyAllPreferencesVisible(boolean isVisible)270     private void verifyAllPreferencesVisible(boolean isVisible) {
271         verifySetPrefToVisible(mScreenTimePreference, isVisible);
272         verifySetPrefToVisible(mBackgroundTimePreference, isVisible);
273         verifySetPrefToVisible(mPowerUsageTimeCategory, isVisible);
274     }
275 
verifyOnePreferenceInvisible(Preference pref)276     private void verifyOnePreferenceInvisible(Preference pref) {
277         verifySetPrefToVisible(mScreenTimePreference, mScreenTimePreference != pref);
278         verifySetPrefToVisible(mBackgroundTimePreference, mBackgroundTimePreference != pref);
279         verifySetPrefToVisible(mPowerUsageTimeCategory, mPowerUsageTimeCategory != pref);
280     }
281 }
282