• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  *
16  */
17 
18 package com.android.settings.fuelgauge;
19 
20 import static com.google.common.truth.Truth.assertThat;
21 
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.Mockito.doReturn;
24 import static org.mockito.Mockito.spy;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.verifyZeroInteractions;
27 import static org.mockito.Mockito.when;
28 
29 import android.app.Activity;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.icu.text.NumberFormat;
33 import android.os.BatteryManager;
34 import android.os.PowerManager;
35 import android.text.TextUtils;
36 
37 import androidx.lifecycle.LifecycleOwner;
38 import androidx.preference.PreferenceFragmentCompat;
39 import androidx.preference.PreferenceScreen;
40 
41 import com.android.settings.R;
42 import com.android.settings.core.BasePreferenceController;
43 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
44 import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
45 import com.android.settings.fuelgauge.batterytip.tips.SmartBatteryTip;
46 import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
47 import com.android.settings.testutils.shadow.ShadowUtils;
48 import com.android.settings.widget.EntityHeaderController;
49 import com.android.settingslib.core.lifecycle.Lifecycle;
50 import com.android.settingslib.widget.UsageProgressBarPreference;
51 
52 import org.junit.After;
53 import org.junit.Before;
54 import org.junit.Test;
55 import org.junit.runner.RunWith;
56 import org.mockito.Mock;
57 import org.mockito.MockitoAnnotations;
58 import org.robolectric.RobolectricTestRunner;
59 import org.robolectric.RuntimeEnvironment;
60 import org.robolectric.Shadows;
61 import org.robolectric.annotation.Config;
62 import org.robolectric.shadows.ShadowPowerManager;
63 
64 @RunWith(RobolectricTestRunner.class)
65 @Config(shadows = {ShadowEntityHeaderController.class, ShadowUtils.class})
66 public class BatteryHeaderPreferenceControllerTest {
67 
68     private static final String PREF_KEY = "battery_header";
69     private static final int BATTERY_LEVEL = 60;
70     private static final int BATTERY_MAX_LEVEL = 100;
71     private static final String TIME_LEFT = "2h30min";
72     private static final String BATTERY_STATUS = "Charging";
73 
74     @Mock
75     private Activity mActivity;
76     @Mock
77     private PreferenceFragmentCompat mPreferenceFragment;
78     @Mock
79     private PreferenceScreen mPreferenceScreen;
80     @Mock
81     private BatteryInfo mBatteryInfo;
82     @Mock
83     private EntityHeaderController mEntityHeaderController;
84     @Mock
85     private UsageProgressBarPreference mBatteryUsageProgressBarPref;
86     @Mock
87     private BatteryStatusFeatureProvider mBatteryStatusFeatureProvider;
88     private BatteryHeaderPreferenceController mController;
89     private Context mContext;
90     private ShadowPowerManager mShadowPowerManager;
91     private Intent mBatteryIntent;
92     private LifecycleOwner mLifecycleOwner;
93     private Lifecycle mLifecycle;
94 
95     @Before
setUp()96     public void setUp() {
97         MockitoAnnotations.initMocks(this);
98 
99         mLifecycleOwner = () -> mLifecycle;
100         mLifecycle = new Lifecycle(mLifecycleOwner);
101         mContext = spy(RuntimeEnvironment.application);
102         ShadowEntityHeaderController.setUseMock(mEntityHeaderController);
103 
104         mBatteryIntent = new Intent();
105         mBatteryIntent.putExtra(BatteryManager.EXTRA_LEVEL, BATTERY_LEVEL);
106         mBatteryIntent.putExtra(BatteryManager.EXTRA_SCALE, 100);
107         mBatteryIntent.putExtra(BatteryManager.EXTRA_PLUGGED, 1);
108         doReturn(mBatteryIntent).when(mContext).registerReceiver(any(), any());
109 
110         doReturn(mBatteryUsageProgressBarPref).when(mPreferenceScreen)
111             .findPreference(BatteryHeaderPreferenceController.KEY_BATTERY_HEADER);
112 
113         mBatteryInfo.batteryLevel = BATTERY_LEVEL;
114 
115         mShadowPowerManager = Shadows.shadowOf(mContext.getSystemService(PowerManager.class));
116 
117         mController = spy(new BatteryHeaderPreferenceController(mContext, PREF_KEY));
118         mLifecycle.addObserver(mController);
119         mController.setActivity(mActivity);
120         mController.setFragment(mPreferenceFragment);
121         mController.setLifecycle(mLifecycle);
122         mController.mBatteryUsageProgressBarPref = mBatteryUsageProgressBarPref;
123         mController.mBatteryStatusFeatureProvider = mBatteryStatusFeatureProvider;
124     }
125 
126     @After
tearDown()127     public void tearDown() {
128         ShadowEntityHeaderController.reset();
129         ShadowUtils.reset();
130     }
131 
132     @Test
displayPreference_displayBatteryLevel()133     public void displayPreference_displayBatteryLevel() {
134         mController.displayPreference(mPreferenceScreen);
135 
136         verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
137         verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
138     }
139 
140     @Test
updatePreference_hasRemainingTime_showRemainingLabel()141     public void updatePreference_hasRemainingTime_showRemainingLabel() {
142         mBatteryInfo.remainingLabel = TIME_LEFT;
143 
144         mController.updateHeaderPreference(mBatteryInfo);
145 
146         verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
147     }
148 
149     @Test
updatePreference_updateBatteryInfo()150     public void updatePreference_updateBatteryInfo() {
151         setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
152 
153         mController.updateHeaderPreference(mBatteryInfo);
154 
155         verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
156         verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
157         verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
158     }
159 
160     @Test
updatePreference_noRemainingTime_showStatusLabel()161     public void updatePreference_noRemainingTime_showStatusLabel() {
162         mBatteryInfo.remainingLabel = null;
163         mBatteryInfo.statusLabel = BATTERY_STATUS;
164 
165         mController.updateHeaderPreference(mBatteryInfo);
166 
167         verify(mBatteryUsageProgressBarPref).setBottomSummary(BATTERY_STATUS);
168     }
169 
170     @Test
updatePreference_statusAnomalous_showStatusLabel()171     public void updatePreference_statusAnomalous_showStatusLabel() {
172         mBatteryInfo.remainingLabel = TIME_LEFT;
173         mBatteryInfo.statusLabel = BATTERY_STATUS;
174         mBatteryInfo.batteryStatus = BatteryManager.BATTERY_STATUS_NOT_CHARGING;
175 
176         mController.updateHeaderPreference(mBatteryInfo);
177 
178         verify(mBatteryUsageProgressBarPref).setBottomSummary(BATTERY_STATUS);
179     }
180 
181     @Test
updatePreference_charging_showFullText()182     public void updatePreference_charging_showFullText() {
183         setChargingState(/* isDischarging */ false, /* updatedByStatusFeature */ false);
184 
185         mController.updateHeaderPreference(mBatteryInfo);
186 
187         final String expectedResult = BATTERY_STATUS + " • " + TIME_LEFT;
188         verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
189     }
190 
191     @Test
updatePreference_powerSaverOn_showPowerSaverOn()192     public void updatePreference_powerSaverOn_showPowerSaverOn() {
193         setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
194         mShadowPowerManager.setIsPowerSaveMode(true);
195 
196         mController.updateHeaderPreference(mBatteryInfo);
197 
198         final String expectedResult = "Battery Saver on • " + TIME_LEFT;
199         verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
200     }
201 
202     @Test
updatePreference_triggerBatteryStatusUpdateTrue_updatePercentageAndUsageOnly()203     public void updatePreference_triggerBatteryStatusUpdateTrue_updatePercentageAndUsageOnly() {
204         setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ true);
205 
206         mController.updateHeaderPreference(mBatteryInfo);
207 
208         verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
209         verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
210     }
211 
212     @Test
updatePreference_triggerBatteryStatusUpdateFalse_updateBatteryInfo()213     public void updatePreference_triggerBatteryStatusUpdateFalse_updateBatteryInfo() {
214         setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
215 
216         mController.updateHeaderPreference(mBatteryInfo);
217 
218         verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
219         verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
220         verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
221     }
222 
223     @Test
updateBatteryStatus_nullLabel_updateSummaryOnly()224     public void updateBatteryStatus_nullLabel_updateSummaryOnly() {
225         setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
226 
227         mController.updateBatteryStatus(null, mBatteryInfo);
228 
229         verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
230     }
231 
232     @Test
updateBatteryStatus_withLabel_showLabelText()233     public void updateBatteryStatus_withLabel_showLabelText() {
234         setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
235 
236         final String label = "Update by battery status • " + TIME_LEFT;
237         mController.updateBatteryStatus(label, mBatteryInfo);
238 
239         verify(mBatteryUsageProgressBarPref).setBottomSummary(label);
240     }
241 
242     @Test
updateHeaderByBatteryTips_lowBatteryTip_showLowBattery()243     public void updateHeaderByBatteryTips_lowBatteryTip_showLowBattery() {
244         setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
245         BatteryTip lowBatteryTip = new LowBatteryTip(
246                 BatteryTip.StateType.NEW, /* powerSaveModeOn */false);
247 
248         mController.updateHeaderByBatteryTips(lowBatteryTip, mBatteryInfo);
249 
250         final String expectedResult = "Low battery • " + TIME_LEFT;
251         verify(mBatteryUsageProgressBarPref).setBottomSummary(expectedResult);
252     }
253 
254     @Test
updateHeaderByBatteryTips_notLowBatteryTip_showRemainingLabel()255     public void updateHeaderByBatteryTips_notLowBatteryTip_showRemainingLabel() {
256         setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
257         BatteryTip lowBatteryTip = new SmartBatteryTip(BatteryTip.StateType.NEW);
258 
259         mController.updateHeaderByBatteryTips(lowBatteryTip, mBatteryInfo);
260 
261         verify(mBatteryUsageProgressBarPref).setBottomSummary(mBatteryInfo.remainingLabel);
262     }
263 
264     @Test
updateHeaderByBatteryTips_noTip_noAction()265     public void updateHeaderByBatteryTips_noTip_noAction() {
266         setChargingState(/* isDischarging */ true, /* updatedByStatusFeature */ false);
267 
268         mController.updateHeaderByBatteryTips(null, mBatteryInfo);
269 
270         verifyZeroInteractions(mBatteryUsageProgressBarPref);
271     }
272 
273     @Test
updateHeaderByBatteryTips_noBatteryInfo_noAction()274     public void updateHeaderByBatteryTips_noBatteryInfo_noAction() {
275         BatteryTip lowBatteryTip = new LowBatteryTip(
276                 BatteryTip.StateType.NEW, /* powerSaveModeOn */false);
277 
278         mController.updateHeaderByBatteryTips(lowBatteryTip, null);
279 
280         verifyZeroInteractions(mBatteryUsageProgressBarPref);
281     }
282 
283     @Test
updatePreference_isOverheat_showEmptyText()284     public void updatePreference_isOverheat_showEmptyText() {
285         mBatteryInfo.isOverheated = true;
286 
287         mController.updateHeaderPreference(mBatteryInfo);
288 
289         verify(mBatteryUsageProgressBarPref).setBottomSummary(null);
290     }
291 
292     @Test
quickUpdateHeaderPreference_onlyUpdateBatteryLevelAndChargingState()293     public void quickUpdateHeaderPreference_onlyUpdateBatteryLevelAndChargingState() {
294         mController.quickUpdateHeaderPreference();
295 
296         verify(mBatteryUsageProgressBarPref).setUsageSummary(formatBatteryPercentageText());
297         verify(mBatteryUsageProgressBarPref).setPercent(BATTERY_LEVEL, BATTERY_MAX_LEVEL);
298     }
299 
300     @Test
getAvailabilityStatus_returnAvailableUnsearchable()301     public void getAvailabilityStatus_returnAvailableUnsearchable() {
302         assertThat(mController.getAvailabilityStatus()).isEqualTo(
303                 BasePreferenceController.AVAILABLE_UNSEARCHABLE);
304     }
305 
306     @Test
displayPreference_batteryNotPresent_isInvisible()307     public void displayPreference_batteryNotPresent_isInvisible() {
308         ShadowUtils.setIsBatteryPresent(false);
309 
310         mController.displayPreference(mPreferenceScreen);
311 
312         assertThat(mBatteryUsageProgressBarPref.isVisible()).isFalse();
313     }
314 
315     @Test
displayPreference_init_showLoading()316     public void displayPreference_init_showLoading() {
317         mController.displayPreference(mPreferenceScreen);
318 
319         verify(mBatteryUsageProgressBarPref).setBottomSummary(
320                 mContext.getString(R.string.settings_license_activity_loading));
321     }
322 
formatBatteryPercentageText()323     private CharSequence formatBatteryPercentageText() {
324         return TextUtils.expandTemplate(mContext.getText(R.string.battery_header_title_alternate),
325                 NumberFormat.getIntegerInstance().format(BATTERY_LEVEL));
326     }
327 
setChargingState(boolean isDischarging, boolean updatedByStatusFeature)328     private void setChargingState(boolean isDischarging, boolean updatedByStatusFeature) {
329         mBatteryInfo.remainingLabel = TIME_LEFT;
330         mBatteryInfo.statusLabel = BATTERY_STATUS;
331         mBatteryInfo.discharging = isDischarging;
332 
333         when(mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(
334                 mController, mBatteryInfo)).thenReturn(updatedByStatusFeature);
335     }
336 }
337