blob: 617c17e484524447c2ce19b674b2e708ae025190 [file] [log] [blame]
Julia Reynolds561d3f42018-01-26 11:31:02 -05001/*
2 * Copyright (C) 2018 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
17package com.android.systemui.volume;
18
Julia Reynolds561d3f42018-01-26 11:31:02 -050019import static com.android.systemui.volume.VolumeDialogControllerImpl.STREAMS;
20
21import static junit.framework.Assert.assertTrue;
22
Rhed Jao46842232018-11-12 14:37:20 +080023import static org.mockito.ArgumentMatchers.any;
Julia Reynolds45d4ab02018-01-31 14:59:14 -050024import static org.mockito.Mockito.verify;
Julia Reynolds45d4ab02018-01-31 14:59:14 -050025
Julia Reynolds561d3f42018-01-26 11:31:02 -050026import android.app.KeyguardManager;
27import android.media.AudioManager;
Rhed Jao46842232018-11-12 14:37:20 +080028import android.os.SystemClock;
Julia Reynolds561d3f42018-01-26 11:31:02 -050029import android.testing.AndroidTestingRunner;
30import android.testing.TestableLooper;
Rhed Jao46842232018-11-12 14:37:20 +080031import android.view.InputDevice;
32import android.view.MotionEvent;
Julia Reynolds561d3f42018-01-26 11:31:02 -050033import android.view.View;
34import android.view.ViewGroup;
Rhed Jao46842232018-11-12 14:37:20 +080035import android.view.accessibility.AccessibilityManager;
Julia Reynolds561d3f42018-01-26 11:31:02 -050036
Brett Chabot84151d92019-02-27 15:37:59 -080037import androidx.test.filters.SmallTest;
38
Julia Reynolds561d3f42018-01-26 11:31:02 -050039import com.android.systemui.SysuiTestCase;
40import com.android.systemui.plugins.VolumeDialogController;
Julia Reynolds45d4ab02018-01-31 14:59:14 -050041import com.android.systemui.plugins.VolumeDialogController.State;
Julia Reynolds561d3f42018-01-26 11:31:02 -050042import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
43
44import org.junit.Before;
45import org.junit.Test;
46import org.junit.runner.RunWith;
Rhed Jao46842232018-11-12 14:37:20 +080047import org.mockito.ArgumentCaptor;
Julia Reynolds561d3f42018-01-26 11:31:02 -050048import org.mockito.Mock;
Rhed Jao46842232018-11-12 14:37:20 +080049import org.mockito.Mockito;
Julia Reynolds561d3f42018-01-26 11:31:02 -050050import org.mockito.MockitoAnnotations;
51
52import java.util.function.Predicate;
53
54@SmallTest
55@RunWith(AndroidTestingRunner.class)
56@TestableLooper.RunWithLooper
57public class VolumeDialogImplTest extends SysuiTestCase {
58
59 VolumeDialogImpl mDialog;
60
61 @Mock
62 VolumeDialogController mController;
63
64 @Mock
65 KeyguardManager mKeyguard;
66
67 @Mock
68 AccessibilityManagerWrapper mAccessibilityMgr;
69
70 @Before
71 public void setup() throws Exception {
72 MockitoAnnotations.initMocks(this);
73
74 mController = mDependency.injectMockDependency(VolumeDialogController.class);
75 mAccessibilityMgr = mDependency.injectMockDependency(AccessibilityManagerWrapper.class);
76 getContext().addMockSystemService(KeyguardManager.class, mKeyguard);
77
78 mDialog = new VolumeDialogImpl(getContext());
79 mDialog.init(0, null);
Julia Reynolds45d4ab02018-01-31 14:59:14 -050080 State state = createShellState();
81 mDialog.onStateChangedH(state);
82 }
83
84 private State createShellState() {
85 State state = new VolumeDialogController.State();
Julia Reynolds561d3f42018-01-26 11:31:02 -050086 for (int i = AudioManager.STREAM_VOICE_CALL; i <= AudioManager.STREAM_ACCESSIBILITY; i++) {
87 VolumeDialogController.StreamState ss = new VolumeDialogController.StreamState();
88 ss.name = STREAMS.get(i);
Julia Reynolds45d4ab02018-01-31 14:59:14 -050089 ss.level = 1;
Julia Reynolds561d3f42018-01-26 11:31:02 -050090 state.states.append(i, ss);
91 }
Julia Reynolds45d4ab02018-01-31 14:59:14 -050092 return state;
Julia Reynolds561d3f42018-01-26 11:31:02 -050093 }
94
95 private void navigateViews(View view, Predicate<View> condition) {
96 if (view instanceof ViewGroup) {
97 ViewGroup viewGroup = (ViewGroup) view;
98 for (int i = 0; i < viewGroup.getChildCount(); i++) {
99 navigateViews(viewGroup.getChildAt(i), condition);
100 }
101 } else {
102 String resourceName = null;
103 try {
104 resourceName = getContext().getResources().getResourceName(view.getId());
105 } catch (Exception e) {}
106 assertTrue("View " + resourceName != null ? resourceName : view.getId()
107 + " failed test", condition.test(view));
108 }
109 }
Rhed Jao46842232018-11-12 14:37:20 +0800110
111 @Test
112 public void testComputeTimeout() {
113 Mockito.reset(mAccessibilityMgr);
114 mDialog.rescheduleTimeoutH();
115 verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
116 VolumeDialogImpl.DIALOG_TIMEOUT_MILLIS,
117 AccessibilityManager.FLAG_CONTENT_CONTROLS);
118 }
119
120 @Test
121 public void testComputeTimeout_withHovering() {
122 Mockito.reset(mAccessibilityMgr);
123 View dialog = mDialog.getDialogView();
124 long uptimeMillis = SystemClock.uptimeMillis();
125 MotionEvent event = MotionEvent.obtain(uptimeMillis, uptimeMillis,
126 MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0);
127 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
128 dialog.dispatchGenericMotionEvent(event);
129 event.recycle();
130 verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
131 VolumeDialogImpl.DIALOG_HOVERING_TIMEOUT_MILLIS,
132 AccessibilityManager.FLAG_CONTENT_CONTROLS);
133 }
134
135 @Test
136 public void testComputeTimeout_withSafetyWarningOn() {
137 Mockito.reset(mAccessibilityMgr);
138 ArgumentCaptor<VolumeDialogController.Callbacks> controllerCallbackCapture =
139 ArgumentCaptor.forClass(VolumeDialogController.Callbacks.class);
140 verify(mController).addCallback(controllerCallbackCapture.capture(), any());
141 VolumeDialogController.Callbacks callbacks = controllerCallbackCapture.getValue();
142 callbacks.onShowSafetyWarning(AudioManager.FLAG_SHOW_UI);
143 verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
144 VolumeDialogImpl.DIALOG_SAFETYWARNING_TIMEOUT_MILLIS,
145 AccessibilityManager.FLAG_CONTENT_TEXT
146 | AccessibilityManager.FLAG_CONTENT_CONTROLS);
147 }
148
Julia Reynoldse904fb32018-02-01 09:27:13 -0500149/*
Julia Reynolds561d3f42018-01-26 11:31:02 -0500150 @Test
151 public void testContentDescriptions() {
152 mDialog.show(SHOW_REASON_UNKNOWN);
153 ViewGroup dialog = mDialog.getDialogView();
154
155 navigateViews(dialog, view -> {
156 if (view instanceof ImageView) {
157 return !TextUtils.isEmpty(view.getContentDescription());
158 } else {
159 return true;
160 }
161 });
162
163 mDialog.dismiss(DISMISS_REASON_UNKNOWN);
164 }
165
Julia Reynolds45d4ab02018-01-31 14:59:14 -0500166 @Test
167 public void testNoDuplicationOfParentState() {
168 mDialog.show(SHOW_REASON_UNKNOWN);
169 ViewGroup dialog = mDialog.getDialogView();
170
171 navigateViews(dialog, view -> !view.isDuplicateParentStateEnabled());
172
173 mDialog.dismiss(DISMISS_REASON_UNKNOWN);
174 }
175
176 @Test
177 public void testNoClickableViewGroups() {
178 mDialog.show(SHOW_REASON_UNKNOWN);
179 ViewGroup dialog = mDialog.getDialogView();
180
181 navigateViews(dialog, view -> {
182 if (view instanceof ViewGroup) {
183 return !view.isClickable();
184 } else {
185 return true;
186 }
187 });
188
189 mDialog.dismiss(DISMISS_REASON_UNKNOWN);
190 }
191
192 @Test
193 public void testTristateToggle_withVibrator() {
194 when(mController.hasVibrator()).thenReturn(true);
195
196 State state = createShellState();
197 state.ringerModeInternal = RINGER_MODE_NORMAL;
198 mDialog.onStateChangedH(state);
199
200 mDialog.show(SHOW_REASON_UNKNOWN);
201 ViewGroup dialog = mDialog.getDialogView();
202
203 // click once, verify updates to vibrate
204 dialog.findViewById(R.id.ringer_icon).performClick();
205 verify(mController, times(1)).setRingerMode(RINGER_MODE_VIBRATE, false);
206
207 // fake the update back to the dialog with the new ringer mode
208 state = createShellState();
209 state.ringerModeInternal = RINGER_MODE_VIBRATE;
210 mDialog.onStateChangedH(state);
211
212 // click once, verify updates to silent
213 dialog.findViewById(R.id.ringer_icon).performClick();
214 verify(mController, times(1)).setRingerMode(RINGER_MODE_SILENT, false);
215 verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
216
217 // fake the update back to the dialog with the new ringer mode
218 state = createShellState();
219 state.states.get(STREAM_RING).level = 0;
220 state.ringerModeInternal = RINGER_MODE_SILENT;
221 mDialog.onStateChangedH(state);
222
223 // click once, verify updates to normal
224 dialog.findViewById(R.id.ringer_icon).performClick();
225 verify(mController, times(1)).setRingerMode(RINGER_MODE_NORMAL, false);
226 verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
227 }
228
229 @Test
230 public void testTristateToggle_withoutVibrator() {
231 when(mController.hasVibrator()).thenReturn(false);
232
233 State state = createShellState();
234 state.ringerModeInternal = RINGER_MODE_NORMAL;
235 mDialog.onStateChangedH(state);
236
237 mDialog.show(SHOW_REASON_UNKNOWN);
238 ViewGroup dialog = mDialog.getDialogView();
239
240 // click once, verify updates to silent
241 dialog.findViewById(R.id.ringer_icon).performClick();
242 verify(mController, times(1)).setRingerMode(RINGER_MODE_SILENT, false);
243 verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
244
245 // fake the update back to the dialog with the new ringer mode
246 state = createShellState();
247 state.states.get(STREAM_RING).level = 0;
248 state.ringerModeInternal = RINGER_MODE_SILENT;
249 mDialog.onStateChangedH(state);
250
251 // click once, verify updates to normal
252 dialog.findViewById(R.id.ringer_icon).performClick();
253 verify(mController, times(1)).setRingerMode(RINGER_MODE_NORMAL, false);
254 verify(mController, times(1)).setStreamVolume(STREAM_RING, 0);
255 }
Julia Reynoldse904fb32018-02-01 09:27:13 -0500256 */
Julia Reynolds561d3f42018-01-26 11:31:02 -0500257}