1 /*
2  * Copyright (C) 2020 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.systemui.qs.tiles
18 
19 import android.content.Context
20 import android.os.Handler
21 import android.testing.AndroidTestingRunner
22 import android.testing.TestableLooper
23 import android.testing.TestableLooper.RunWithLooper
24 import android.view.View
25 import androidx.test.filters.SmallTest
26 import com.android.internal.logging.MetricsLogger
27 import com.android.systemui.R
28 import com.android.systemui.SysuiTestCase
29 import com.android.systemui.classifier.FalsingManagerFake
30 import com.android.systemui.plugins.ActivityStarter
31 import com.android.systemui.plugins.qs.QSTile
32 import com.android.systemui.plugins.statusbar.StatusBarStateController
33 import com.android.systemui.qs.QSHost
34 import com.android.systemui.qs.QsEventLogger
35 import com.android.systemui.qs.logging.QSLogger
36 import com.android.systemui.qs.tileimpl.QSTileImpl
37 import com.android.systemui.statusbar.policy.BatteryController
38 import com.android.systemui.util.settings.FakeSettings
39 import com.android.systemui.util.settings.SecureSettings
40 import com.google.common.truth.Truth.assertThat
41 import org.junit.After
42 import org.junit.Assert.assertEquals
43 import org.junit.Before
44 import org.junit.Test
45 import org.junit.runner.RunWith
46 import org.mockito.Mock
47 import org.mockito.Mockito.clearInvocations
48 import org.mockito.Mockito.never
49 import org.mockito.Mockito.verify
50 import org.mockito.Mockito.`when`
51 import org.mockito.MockitoAnnotations
52 
53 @RunWith(AndroidTestingRunner::class)
54 @RunWithLooper(setAsMainLooper = true)
55 @SmallTest
56 class BatterySaverTileTest : SysuiTestCase() {
57 
58     companion object {
59         private const val USER = 10
60     }
61 
62     @Mock
63     private lateinit var userContext: Context
64     @Mock
65     private lateinit var qsHost: QSHost
66     @Mock
67     private lateinit var uiEventLogger: QsEventLogger
68     @Mock
69     private lateinit var metricsLogger: MetricsLogger
70     @Mock
71     private lateinit var statusBarStateController: StatusBarStateController
72     @Mock
73     private lateinit var activityStarter: ActivityStarter
74     @Mock
75     private lateinit var qsLogger: QSLogger
76     @Mock
77     private lateinit var batteryController: BatteryController
78     @Mock
79     private lateinit var view: View
80     private lateinit var secureSettings: SecureSettings
81     private lateinit var testableLooper: TestableLooper
82     private lateinit var tile: BatterySaverTile
83 
84     @Before
85     fun setUp() {
86         MockitoAnnotations.initMocks(this)
87         testableLooper = TestableLooper.get(this)
88         `when`(qsHost.context).thenReturn(mContext)
89         `when`(qsHost.userContext).thenReturn(userContext)
90         `when`(userContext.userId).thenReturn(USER)
91 
92         secureSettings = FakeSettings()
93 
94         tile = BatterySaverTile(
95                 qsHost,
96                 uiEventLogger,
97                 testableLooper.looper,
98                 Handler(testableLooper.looper),
99                 FalsingManagerFake(),
100                 metricsLogger,
101                 statusBarStateController,
102                 activityStarter,
103                 qsLogger,
104                 batteryController,
105                 secureSettings)
106 
107         tile.initialize()
108         testableLooper.processAllMessages()
109     }
110 
111     @After
112     fun tearDown() {
113         tile.destroy()
114         testableLooper.processAllMessages()
115     }
116 
117     @Test
118     fun testSettingWithCorrectUser() {
119         assertEquals(USER, tile.mSetting.currentUser)
120     }
121 
122     @Test
123     fun testSettingChangesUser() {
124         tile.userSwitch(USER + 1)
125 
126         testableLooper.processAllMessages()
127 
128         assertEquals(USER + 1, tile.mSetting.currentUser)
129     }
130 
131     @Test
132     fun testClickingPowerSavePassesView() {
133         tile.onPowerSaveChanged(true)
134         tile.handleClick(view)
135 
136         tile.onPowerSaveChanged(false)
137         tile.handleClick(view)
138 
139         verify(batteryController).setPowerSaveMode(true, view)
140         verify(batteryController).setPowerSaveMode(false, view)
141     }
142 
143     @Test
144     fun testStopListeningClearsViewInController() {
145         clearInvocations(batteryController)
146         tile.handleSetListening(true)
147         verify(batteryController, never()).clearLastPowerSaverStartView()
148 
149         tile.handleSetListening(false)
150         verify(batteryController).clearLastPowerSaverStartView()
151     }
152 
153     @Test
154     fun testIcon_whenBatterySaverDisabled_isOffState() {
155         val state = QSTile.BooleanState()
156         tile.onPowerSaveChanged(false)
157 
158         tile.handleUpdateState(state, /* arg= */ null)
159 
160         assertThat(state.icon)
161                 .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_battery_saver_icon_off))
162     }
163 
164     @Test
165     fun testIcon_whenBatterySaverEnabled_isOnState() {
166         val state = QSTile.BooleanState()
167         tile.onPowerSaveChanged(true)
168 
169         tile.handleUpdateState(state, /* arg= */ null)
170 
171         assertThat(state.icon)
172                 .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_battery_saver_icon_on))
173     }
174 }