1 /* 2 * Copyright (C) 2017 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.volume; 18 19 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.Mockito.mock; 23 import static org.mockito.Mockito.never; 24 import static org.mockito.Mockito.times; 25 import static org.mockito.Mockito.verify; 26 import static org.mockito.Mockito.when; 27 28 import android.app.ActivityManager; 29 import android.app.KeyguardManager; 30 import android.app.NotificationManager; 31 import android.content.BroadcastReceiver; 32 import android.content.Context; 33 import android.content.IntentFilter; 34 import android.content.pm.PackageManager; 35 import android.media.AudioManager; 36 import android.media.IAudioService; 37 import android.media.session.MediaSession; 38 import android.os.Handler; 39 import android.os.Process; 40 import android.testing.AndroidTestingRunner; 41 import android.testing.TestableLooper; 42 import android.view.accessibility.AccessibilityManager; 43 44 import androidx.test.filters.SmallTest; 45 46 import com.android.systemui.SysuiTestCase; 47 import com.android.systemui.broadcast.BroadcastDispatcher; 48 import com.android.systemui.dump.DumpManager; 49 import com.android.systemui.keyguard.WakefulnessLifecycle; 50 import com.android.systemui.settings.UserTracker; 51 import com.android.systemui.statusbar.VibratorHelper; 52 import com.android.systemui.util.RingerModeLiveData; 53 import com.android.systemui.util.RingerModeTracker; 54 import com.android.systemui.util.concurrency.FakeExecutor; 55 import com.android.systemui.util.concurrency.FakeThreadFactory; 56 import com.android.systemui.util.concurrency.ThreadFactory; 57 import com.android.systemui.util.time.FakeSystemClock; 58 59 import org.junit.Before; 60 import org.junit.Test; 61 import org.junit.runner.RunWith; 62 import org.mockito.ArgumentCaptor; 63 import org.mockito.Mock; 64 import org.mockito.MockitoAnnotations; 65 66 import java.util.concurrent.Executor; 67 68 @RunWith(AndroidTestingRunner.class) 69 @SmallTest 70 @TestableLooper.RunWithLooper 71 public class VolumeDialogControllerImplTest extends SysuiTestCase { 72 73 TestableVolumeDialogControllerImpl mVolumeController; 74 VolumeDialogControllerImpl.C mCallback; 75 @Mock 76 private BroadcastDispatcher mBroadcastDispatcher; 77 @Mock 78 private RingerModeTracker mRingerModeTracker; 79 @Mock 80 private RingerModeLiveData mRingerModeLiveData; 81 @Mock 82 private RingerModeLiveData mRingerModeInternalLiveData; 83 private final FakeThreadFactory mThreadFactory = new FakeThreadFactory( 84 new FakeExecutor(new FakeSystemClock())); 85 @Mock 86 private AudioManager mAudioManager; 87 @Mock 88 private NotificationManager mNotificationManager; 89 @Mock 90 private VibratorHelper mVibrator; 91 @Mock 92 private IAudioService mIAudioService; 93 @Mock 94 private AccessibilityManager mAccessibilityManager; 95 @Mock 96 private PackageManager mPackageManager; 97 @Mock 98 private WakefulnessLifecycle mWakefullnessLifcycle; 99 @Mock 100 private KeyguardManager mKeyguardManager; 101 @Mock 102 private ActivityManager mActivityManager; 103 @Mock 104 private UserTracker mUserTracker; 105 @Mock 106 private DumpManager mDumpManager; 107 108 109 @Before setup()110 public void setup() throws Exception { 111 MockitoAnnotations.initMocks(this); 112 113 when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData); 114 when(mRingerModeTracker.getRingerModeInternal()).thenReturn(mRingerModeInternalLiveData); 115 // Initial non-set value 116 when(mRingerModeLiveData.getValue()).thenReturn(-1); 117 when(mRingerModeInternalLiveData.getValue()).thenReturn(-1); 118 when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser()); 119 when(mUserTracker.getUserContext()).thenReturn(mContext); 120 // Enable group volume adjustments 121 mContext.getOrCreateTestableResources().addOverride( 122 com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions, 123 true); 124 125 mCallback = mock(VolumeDialogControllerImpl.C.class); 126 mThreadFactory.setLooper(TestableLooper.get(this).getLooper()); 127 mVolumeController = new TestableVolumeDialogControllerImpl(mContext, 128 mBroadcastDispatcher, mRingerModeTracker, mThreadFactory, mAudioManager, 129 mNotificationManager, mVibrator, mIAudioService, mAccessibilityManager, 130 mPackageManager, mWakefullnessLifcycle, mKeyguardManager, 131 mActivityManager, mUserTracker, mDumpManager, mCallback); 132 mVolumeController.setEnableDialogs(true, true); 133 } 134 135 @Test testRegisteredWithDispatcher()136 public void testRegisteredWithDispatcher() { 137 verify(mBroadcastDispatcher).registerReceiverWithHandler(any(BroadcastReceiver.class), 138 any(IntentFilter.class), 139 any(Handler.class)); // VolumeDialogControllerImpl does not call with user 140 } 141 142 @Test testVolumeChangeW_deviceNotInteractiveAOD()143 public void testVolumeChangeW_deviceNotInteractiveAOD() { 144 mVolumeController.setDeviceInteractive(false); 145 when(mWakefullnessLifcycle.getWakefulness()).thenReturn( 146 WakefulnessLifecycle.WAKEFULNESS_AWAKE); 147 mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI); 148 verify(mCallback, never()).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED, false, 149 LOCK_TASK_MODE_NONE); 150 } 151 152 @Test testVolumeChangeW_deviceInteractive()153 public void testVolumeChangeW_deviceInteractive() { 154 mVolumeController.setDeviceInteractive(true); 155 when(mWakefullnessLifcycle.getWakefulness()).thenReturn( 156 WakefulnessLifecycle.WAKEFULNESS_AWAKE); 157 mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI); 158 verify(mCallback, times(1)).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED, false, 159 LOCK_TASK_MODE_NONE); 160 } 161 162 @Test testVolumeChangeW_deviceInteractive_StartedSleeping()163 public void testVolumeChangeW_deviceInteractive_StartedSleeping() { 164 mVolumeController.setDeviceInteractive(true); 165 when(mWakefullnessLifcycle.getWakefulness()).thenReturn( 166 WakefulnessLifecycle.WAKEFULNESS_AWAKE); 167 mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI); 168 mVolumeController.setDeviceInteractive(false); 169 when(mWakefullnessLifcycle.getWakefulness()).thenReturn( 170 WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP); 171 mVolumeController.onVolumeChangedW(0, AudioManager.FLAG_SHOW_UI); 172 verify(mCallback, times(1)).onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED, false, 173 LOCK_TASK_MODE_NONE); 174 } 175 176 @Test testVolumeChangeW_deviceOutFromBLEHeadset_doStateChanged()177 public void testVolumeChangeW_deviceOutFromBLEHeadset_doStateChanged() { 178 mVolumeController.setDeviceInteractive(false); 179 when(mWakefullnessLifcycle.getWakefulness()).thenReturn( 180 WakefulnessLifecycle.WAKEFULNESS_AWAKE); 181 when(mAudioManager.getDevicesForStream(AudioManager.STREAM_VOICE_CALL)).thenReturn( 182 AudioManager.DEVICE_OUT_BLE_HEADSET); 183 184 mVolumeController.onVolumeChangedW( 185 AudioManager.STREAM_VOICE_CALL, AudioManager.FLAG_SHOW_UI); 186 187 verify(mCallback, times(1)).onStateChanged(any()); 188 } 189 190 @Test testVolumeChangeW_deviceOutFromA2DP_doStateChanged()191 public void testVolumeChangeW_deviceOutFromA2DP_doStateChanged() { 192 mVolumeController.setDeviceInteractive(false); 193 when(mWakefullnessLifcycle.getWakefulness()).thenReturn( 194 WakefulnessLifecycle.WAKEFULNESS_AWAKE); 195 when(mAudioManager.getDevicesForStream(AudioManager.STREAM_VOICE_CALL)).thenReturn( 196 AudioManager.DEVICE_OUT_BLUETOOTH_A2DP); 197 198 mVolumeController.onVolumeChangedW( 199 AudioManager.STREAM_VOICE_CALL, AudioManager.FLAG_SHOW_UI); 200 201 verify(mCallback, never()).onStateChanged(any()); 202 } 203 204 @Test testOnRemoteVolumeChanged_newStream_noNullPointer()205 public void testOnRemoteVolumeChanged_newStream_noNullPointer() { 206 MediaSession.Token token = new MediaSession.Token(Process.myUid(), null); 207 mVolumeController.mMediaSessionsCallbacksW.onRemoteVolumeChanged(token, 0); 208 } 209 210 @Test testOnRemoteRemove_newStream_noNullPointer()211 public void testOnRemoteRemove_newStream_noNullPointer() { 212 MediaSession.Token token = new MediaSession.Token(Process.myUid(), null); 213 mVolumeController.mMediaSessionsCallbacksW.onRemoteRemoved(token); 214 } 215 216 @Test testRingerModeLiveDataObserving()217 public void testRingerModeLiveDataObserving() { 218 verify(mRingerModeLiveData).observeForever(any()); 219 verify(mRingerModeInternalLiveData).observeForever(any()); 220 } 221 222 @Test testAddCallbackWithUserTracker()223 public void testAddCallbackWithUserTracker() { 224 verify(mUserTracker).addCallback(any(UserTracker.Callback.class), any(Executor.class)); 225 } 226 227 static class TestableVolumeDialogControllerImpl extends VolumeDialogControllerImpl { 228 private final WakefulnessLifecycle.Observer mWakefullessLifecycleObserver; 229 TestableVolumeDialogControllerImpl( Context context, BroadcastDispatcher broadcastDispatcher, RingerModeTracker ringerModeTracker, ThreadFactory theadFactory, AudioManager audioManager, NotificationManager notificationManager, VibratorHelper optionalVibrator, IAudioService iAudioService, AccessibilityManager accessibilityManager, PackageManager packageManager, WakefulnessLifecycle wakefulnessLifecycle, KeyguardManager keyguardManager, ActivityManager activityManager, UserTracker userTracker, DumpManager dumpManager, C callback)230 TestableVolumeDialogControllerImpl( 231 Context context, 232 BroadcastDispatcher broadcastDispatcher, 233 RingerModeTracker ringerModeTracker, 234 ThreadFactory theadFactory, 235 AudioManager audioManager, 236 NotificationManager notificationManager, 237 VibratorHelper optionalVibrator, 238 IAudioService iAudioService, 239 AccessibilityManager accessibilityManager, 240 PackageManager packageManager, 241 WakefulnessLifecycle wakefulnessLifecycle, 242 KeyguardManager keyguardManager, 243 ActivityManager activityManager, 244 UserTracker userTracker, 245 DumpManager dumpManager, 246 C callback) { 247 super(context, broadcastDispatcher, ringerModeTracker, theadFactory, audioManager, 248 notificationManager, optionalVibrator, iAudioService, accessibilityManager, 249 packageManager, wakefulnessLifecycle, keyguardManager, 250 activityManager, userTracker, dumpManager); 251 mCallbacks = callback; 252 253 ArgumentCaptor<WakefulnessLifecycle.Observer> observerCaptor = 254 ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class); 255 verify(wakefulnessLifecycle).addObserver(observerCaptor.capture()); 256 mWakefullessLifecycleObserver = observerCaptor.getValue(); 257 } 258 setDeviceInteractive(boolean interactive)259 public void setDeviceInteractive(boolean interactive) { 260 if (interactive) { 261 mWakefullessLifecycleObserver.onStartedWakingUp(); 262 } else { 263 mWakefullessLifecycleObserver.onFinishedGoingToSleep(); 264 } 265 } 266 } 267 268 // static class TestableVolumeDialogControllerImpl extends VolumeDialogControllerImpl { 269 // TestableVolumeDialogControllerImpl(Context context, C callback, 270 // BroadcastDispatcher broadcastDispatcher, RingerModeTracker ringerModeTracker, 271 // ThreadFactory threadFactory) { 272 // super( 273 // context, broadcastDispatcher, 274 // s == null ? Optional.empty() : Optional.of(() -> s), ringerModeTracker); 275 // mCallbacks = callback; 276 // } 277 // } 278 279 } 280