1 /*
2  * Copyright (C) 2021 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 package com.android.settings.fuelgauge;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.ArgumentMatchers.anyInt;
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.when;
27 
28 import android.accessibilityservice.AccessibilityServiceInfo;
29 import android.content.Context;
30 import android.os.LocaleList;
31 import android.view.accessibility.AccessibilityManager;
32 
33 import com.android.settings.testutils.FakeFeatureFactory;
34 
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.mockito.Mock;
39 import org.mockito.MockitoAnnotations;
40 import org.robolectric.RobolectricTestRunner;
41 import org.robolectric.RuntimeEnvironment;
42 
43 import java.util.Arrays;
44 import java.util.ArrayList;
45 import java.util.Locale;
46 
47 @RunWith(RobolectricTestRunner.class)
48 public final class BatteryChartViewTest {
49 
50     private Context mContext;
51     private BatteryChartView mBatteryChartView;
52     private FakeFeatureFactory mFeatureFactory;
53     private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
54 
55     @Mock private AccessibilityServiceInfo mockAccessibilityServiceInfo;
56     @Mock private AccessibilityManager mockAccessibilityManager;
57 
58     @Before
setUp()59     public void setUp() {
60         MockitoAnnotations.initMocks(this);
61         mFeatureFactory = FakeFeatureFactory.setupForTest();
62         mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
63         mContext = spy(RuntimeEnvironment.application);
64         mContext.getResources().getConfiguration().setLocales(
65             new LocaleList(new Locale("en_US")));
66         mBatteryChartView = new BatteryChartView(mContext);
67         doReturn(mockAccessibilityManager).when(mContext)
68             .getSystemService(AccessibilityManager.class);
69         doReturn("TalkBackService").when(mockAccessibilityServiceInfo).getId();
70         doReturn(Arrays.asList(mockAccessibilityServiceInfo))
71             .when(mockAccessibilityManager)
72             .getEnabledAccessibilityServiceList(anyInt());
73     }
74 
75     @Test
testIsAccessibilityEnabled_disable_returnFalse()76     public void testIsAccessibilityEnabled_disable_returnFalse() {
77         doReturn(false).when(mockAccessibilityManager).isEnabled();
78         assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isFalse();
79     }
80 
81     @Test
testIsAccessibilityEnabled_emptyInfo_returnFalse()82     public void testIsAccessibilityEnabled_emptyInfo_returnFalse() {
83         doReturn(true).when(mockAccessibilityManager).isEnabled();
84         doReturn(new ArrayList<AccessibilityServiceInfo>())
85             .when(mockAccessibilityManager)
86             .getEnabledAccessibilityServiceList(anyInt());
87 
88         assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isFalse();
89     }
90 
91     @Test
testIsAccessibilityEnabled_validServiceId_returnTrue()92     public void testIsAccessibilityEnabled_validServiceId_returnTrue() {
93         doReturn(true).when(mockAccessibilityManager).isEnabled();
94         assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isTrue();
95     }
96 
97     @Test
testSetSelectedIndex_invokesCallback()98     public void testSetSelectedIndex_invokesCallback() {
99         final int selectedIndex[] = new int[1];
100         final int expectedIndex = 2;
101         mBatteryChartView.mSelectedIndex = 1;
102         mBatteryChartView.setOnSelectListener(
103             trapezoidIndex -> {
104                 selectedIndex[0] = trapezoidIndex;
105             });
106 
107         mBatteryChartView.setSelectedIndex(expectedIndex);
108 
109         assertThat(mBatteryChartView.mSelectedIndex)
110             .isEqualTo(expectedIndex);
111         assertThat(selectedIndex[0]).isEqualTo(expectedIndex);
112     }
113 
114     @Test
testSetSelectedIndex_sameIndex_notInvokesCallback()115     public void testSetSelectedIndex_sameIndex_notInvokesCallback() {
116         final int selectedIndex[] = new int[1];
117         final int expectedIndex = 1;
118         mBatteryChartView.mSelectedIndex = expectedIndex;
119         mBatteryChartView.setOnSelectListener(
120             trapezoidIndex -> {
121                 selectedIndex[0] = trapezoidIndex;
122             });
123 
124         mBatteryChartView.setSelectedIndex(expectedIndex);
125 
126         assertThat(selectedIndex[0]).isNotEqualTo(expectedIndex);
127     }
128 
129     @Test
testClickable_isChartGraphSlotsEnabledIsFalse_notClickable()130     public void testClickable_isChartGraphSlotsEnabledIsFalse_notClickable() {
131         mBatteryChartView.setClickableForce(true);
132         when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
133             .thenReturn(false);
134 
135         mBatteryChartView.onAttachedToWindow();
136         assertThat(mBatteryChartView.isClickable()).isFalse();
137         assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull();
138     }
139 
140     @Test
testClickable_accessibilityIsDisabled_clickable()141     public void testClickable_accessibilityIsDisabled_clickable() {
142         mBatteryChartView.setClickableForce(true);
143         when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
144             .thenReturn(true);
145         doReturn(false).when(mockAccessibilityManager).isEnabled();
146 
147         mBatteryChartView.onAttachedToWindow();
148         assertThat(mBatteryChartView.isClickable()).isTrue();
149         assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull();
150     }
151 
152     @Test
testClickable_accessibilityIsEnabledWithoutValidId_clickable()153     public void testClickable_accessibilityIsEnabledWithoutValidId_clickable() {
154         mBatteryChartView.setClickableForce(true);
155         when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
156             .thenReturn(true);
157         doReturn(true).when(mockAccessibilityManager).isEnabled();
158         doReturn(new ArrayList<AccessibilityServiceInfo>())
159             .when(mockAccessibilityManager)
160             .getEnabledAccessibilityServiceList(anyInt());
161 
162         mBatteryChartView.onAttachedToWindow();
163         assertThat(mBatteryChartView.isClickable()).isTrue();
164         assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNull();
165     }
166 
167     @Test
testClickable_accessibilityIsEnabledWithValidId_notClickable()168     public void testClickable_accessibilityIsEnabledWithValidId_notClickable() {
169         mBatteryChartView.setClickableForce(true);
170         when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
171             .thenReturn(true);
172         doReturn(true).when(mockAccessibilityManager).isEnabled();
173 
174         mBatteryChartView.onAttachedToWindow();
175         assertThat(mBatteryChartView.isClickable()).isFalse();
176         assertThat(mBatteryChartView.mTrapezoidCurvePaint).isNotNull();
177     }
178 
179     @Test
testClickable_restoreFromNonClickableState()180     public void testClickable_restoreFromNonClickableState() {
181         final int[] levels = new int[13];
182         for (int index = 0; index < levels.length; index++) {
183             levels[index] = index + 1;
184         }
185         mBatteryChartView.setTrapezoidCount(12);
186         mBatteryChartView.setLevels(levels);
187         mBatteryChartView.setClickableForce(true);
188         when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
189             .thenReturn(true);
190         doReturn(true).when(mockAccessibilityManager).isEnabled();
191         mBatteryChartView.onAttachedToWindow();
192         // Ensures the testing environment is correct.
193         assertThat(mBatteryChartView.isClickable()).isFalse();
194         // Turns off accessibility service.
195         doReturn(false).when(mockAccessibilityManager).isEnabled();
196 
197         mBatteryChartView.onAttachedToWindow();
198 
199         assertThat(mBatteryChartView.isClickable()).isTrue();
200     }
201 
202     @Test
testOnAttachedToWindow_addAccessibilityStateChangeListener()203     public void testOnAttachedToWindow_addAccessibilityStateChangeListener() {
204         mBatteryChartView.onAttachedToWindow();
205         verify(mockAccessibilityManager)
206             .addAccessibilityStateChangeListener(mBatteryChartView);
207     }
208 
209     @Test
testOnDetachedFromWindow_removeAccessibilityStateChangeListener()210     public void testOnDetachedFromWindow_removeAccessibilityStateChangeListener() {
211         mBatteryChartView.onAttachedToWindow();
212         mBatteryChartView.mHandler.postDelayed(
213             mBatteryChartView.mUpdateClickableStateRun, 1000);
214 
215         mBatteryChartView.onDetachedFromWindow();
216 
217         verify(mockAccessibilityManager)
218             .removeAccessibilityStateChangeListener(mBatteryChartView);
219         assertThat(mBatteryChartView.mHandler.hasCallbacks(
220                 mBatteryChartView.mUpdateClickableStateRun))
221             .isFalse();
222     }
223 
224     @Test
testOnAccessibilityStateChanged_postUpdateStateRunnable()225     public void testOnAccessibilityStateChanged_postUpdateStateRunnable() {
226         mBatteryChartView.mHandler = spy(mBatteryChartView.mHandler);
227         mBatteryChartView.onAccessibilityStateChanged(/*enabled=*/ true);
228 
229         verify(mBatteryChartView.mHandler)
230             .removeCallbacks(mBatteryChartView.mUpdateClickableStateRun);
231         verify(mBatteryChartView.mHandler)
232             .postDelayed(mBatteryChartView.mUpdateClickableStateRun, 500L);
233     }
234 }
235