1 /*
2  * Copyright (C) 2021 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.systemui.battery
17 
18 import android.testing.AndroidTestingRunner
19 import android.testing.TestableLooper.RunWithLooper
20 import android.widget.ImageView
21 import androidx.test.filters.SmallTest
22 import com.android.systemui.R
23 import com.android.systemui.SysuiTestCase
24 import com.android.systemui.battery.BatteryMeterView.BatteryEstimateFetcher
25 import com.android.systemui.statusbar.policy.BatteryController.EstimateFetchCompletion
26 import com.google.common.truth.Truth.assertThat
27 import org.junit.Before
28 import org.junit.Test
29 import org.junit.runner.RunWith
30 import org.mockito.MockitoAnnotations
31 
32 @SmallTest
33 @RunWith(AndroidTestingRunner::class)
34 @RunWithLooper
35 class BatteryMeterViewTest : SysuiTestCase() {
36 
37     private lateinit var mBatteryMeterView: BatteryMeterView
38 
39     @Before
40     fun setUp() {
41         MockitoAnnotations.initMocks(this)
42         mBatteryMeterView = BatteryMeterView(mContext, null)
43     }
44 
45     @Test
46     fun updatePercentText_estimateModeAndNotCharging_estimateFetched() {
47         mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
48         mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
49 
50         mBatteryMeterView.updatePercentText()
51 
52         assertThat(mBatteryMeterView.batteryPercentViewText).isEqualTo(ESTIMATE)
53     }
54 
55     @Test
56     fun updatePercentText_noBatteryEstimateFetcher_noCrash() {
57         mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
58 
59         mBatteryMeterView.updatePercentText()
60         // No assert needed
61     }
62 
63     @Test
64     fun contentDescription_unknown() {
65         mBatteryMeterView.onBatteryUnknownStateChanged(true)
66 
67         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
68                 context.getString(R.string.accessibility_battery_unknown)
69         )
70     }
71 
72     @Test
73     fun contentDescription_estimate() {
74         mBatteryMeterView.onBatteryLevelChanged(15, false)
75         mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
76         mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
77 
78         mBatteryMeterView.updatePercentText()
79 
80         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
81                 context.getString(
82                         R.string.accessibility_battery_level_with_estimate, 15, ESTIMATE
83                 )
84         )
85     }
86 
87     @Test
88     fun contentDescription_estimateAndBatteryDefender() {
89         mBatteryMeterView.onBatteryLevelChanged(17, false)
90         mBatteryMeterView.onIsBatteryDefenderChanged(true)
91         mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
92         mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
93 
94         mBatteryMeterView.updatePercentText()
95 
96         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
97                 context.getString(
98                         R.string.accessibility_battery_level_charging_paused_with_estimate,
99                         17,
100                         ESTIMATE,
101                 )
102         )
103     }
104 
105     @Test
106     fun contentDescription_batteryDefender() {
107         mBatteryMeterView.onBatteryLevelChanged(90, false)
108         mBatteryMeterView.onIsBatteryDefenderChanged(true)
109 
110         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
111                 context.getString(R.string.accessibility_battery_level_charging_paused, 90)
112         )
113     }
114 
115     @Test
116     fun contentDescription_charging() {
117         mBatteryMeterView.onBatteryLevelChanged(45, true)
118 
119         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
120                 context.getString(R.string.accessibility_battery_level_charging, 45)
121         )
122     }
123 
124     @Test
125     fun contentDescription_notCharging() {
126         mBatteryMeterView.onBatteryLevelChanged(45, false)
127 
128         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
129                 context.getString(R.string.accessibility_battery_level, 45)
130         )
131     }
132 
133     @Test
134     fun contentDescription_isIncompatibleCharging_notCharging() {
135         mBatteryMeterView.onBatteryLevelChanged(45, true)
136         mBatteryMeterView.onIsIncompatibleChargingChanged(true)
137 
138         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
139                 context.getString(R.string.accessibility_battery_level, 45)
140         )
141     }
142 
143     @Test
144     fun changesFromEstimateToPercent_textAndContentDescriptionChanges() {
145         mBatteryMeterView.onBatteryLevelChanged(15, false)
146         mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
147         mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
148 
149         mBatteryMeterView.updatePercentText()
150 
151         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
152                 context.getString(
153                         R.string.accessibility_battery_level_with_estimate, 15, ESTIMATE
154                 )
155         )
156 
157         // Update the show mode from estimate to percent
158         mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON)
159 
160         assertThat(mBatteryMeterView.batteryPercentViewText).isEqualTo("15%")
161         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
162                 context.getString(R.string.accessibility_battery_level, 15)
163         )
164     }
165 
166     @Test
167     fun contentDescription_manyUpdates_alwaysUpdated() {
168         // BatteryDefender
169         mBatteryMeterView.onBatteryLevelChanged(90, false)
170         mBatteryMeterView.onIsBatteryDefenderChanged(true)
171         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
172                 context.getString(R.string.accessibility_battery_level_charging_paused, 90)
173         )
174 
175         // BatteryDefender & estimate
176         mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
177         mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
178         mBatteryMeterView.updatePercentText()
179         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
180                 context.getString(
181                         R.string.accessibility_battery_level_charging_paused_with_estimate,
182                         90,
183                         ESTIMATE,
184                 )
185         )
186 
187         // Just estimate
188         mBatteryMeterView.onIsBatteryDefenderChanged(false)
189         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
190                 context.getString(
191                         R.string.accessibility_battery_level_with_estimate,
192                         90,
193                         ESTIMATE,
194                 )
195         )
196 
197         // Just percent
198         mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON)
199         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
200                 context.getString(R.string.accessibility_battery_level, 90)
201         )
202 
203         // Charging
204         mBatteryMeterView.onBatteryLevelChanged(90, true)
205         assertThat(mBatteryMeterView.contentDescription).isEqualTo(
206                 context.getString(R.string.accessibility_battery_level_charging, 90)
207         )
208     }
209 
210     @Test
211     fun isBatteryDefenderChanged_true_drawableGetsTrue() {
212         mBatteryMeterView.setDisplayShieldEnabled(true)
213         val drawable = getBatteryDrawable()
214 
215         mBatteryMeterView.onIsBatteryDefenderChanged(true)
216 
217         assertThat(drawable.displayShield).isTrue()
218     }
219 
220     @Test
221     fun isBatteryDefenderChanged_false_drawableGetsFalse() {
222         mBatteryMeterView.setDisplayShieldEnabled(true)
223         val drawable = getBatteryDrawable()
224 
225         // Start as true
226         mBatteryMeterView.onIsBatteryDefenderChanged(true)
227 
228         // Update to false
229         mBatteryMeterView.onIsBatteryDefenderChanged(false)
230 
231         assertThat(drawable.displayShield).isFalse()
232     }
233 
234     @Test
235     fun isBatteryDefenderChanged_true_featureflagOff_drawableGetsFalse() {
236         mBatteryMeterView.setDisplayShieldEnabled(false)
237         val drawable = getBatteryDrawable()
238 
239         mBatteryMeterView.onIsBatteryDefenderChanged(true)
240 
241         assertThat(drawable.displayShield).isFalse()
242     }
243 
244     @Test
245     fun isIncompatibleChargingChanged_true_drawableGetsChargingFalse() {
246         mBatteryMeterView.onBatteryLevelChanged(45, true)
247         val drawable = getBatteryDrawable()
248 
249         mBatteryMeterView.onIsIncompatibleChargingChanged(true)
250 
251         assertThat(drawable.getCharging()).isFalse()
252     }
253 
254     @Test
255     fun isIncompatibleChargingChanged_false_drawableGetsChargingTrue() {
256         mBatteryMeterView.onBatteryLevelChanged(45, true)
257         val drawable = getBatteryDrawable()
258 
259         mBatteryMeterView.onIsIncompatibleChargingChanged(false)
260 
261         assertThat(drawable.getCharging()).isTrue()
262     }
263 
264     private fun getBatteryDrawable(): AccessorizedBatteryDrawable {
265         return (mBatteryMeterView.getChildAt(0) as ImageView)
266                 .drawable as AccessorizedBatteryDrawable
267     }
268 
269     private class Fetcher : BatteryEstimateFetcher {
270         override fun fetchBatteryTimeRemainingEstimate(completion: EstimateFetchCompletion) {
271             completion.onBatteryRemainingEstimateRetrieved(ESTIMATE)
272         }
273     }
274 
275     private companion object {
276         const val ESTIMATE = "2 hours 2 minutes"
277     }
278 }
279