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.settings.slices; 18 19 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_SLICES_URI; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.Mockito.never; 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.content.BroadcastReceiver; 29 import android.content.ContentResolver; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.IntentFilter; 33 import android.media.AudioManager; 34 import android.net.Uri; 35 36 import com.android.settings.notification.MediaVolumePreferenceController; 37 import com.android.settings.notification.RingVolumePreferenceController; 38 import com.android.settings.notification.VolumeSeekBarPreferenceController; 39 import com.android.settingslib.SliceBroadcastRelay; 40 41 import org.junit.After; 42 import org.junit.Before; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 import org.mockito.Mock; 46 import org.mockito.MockitoAnnotations; 47 import org.robolectric.RobolectricTestRunner; 48 import org.robolectric.RuntimeEnvironment; 49 import org.robolectric.annotation.Config; 50 import org.robolectric.annotation.Implementation; 51 import org.robolectric.annotation.Implements; 52 import org.robolectric.annotation.Resetter; 53 54 @RunWith(RobolectricTestRunner.class) 55 @Config(shadows = VolumeSliceHelperTest.ShadowSliceBroadcastRelay.class) 56 public class VolumeSliceHelperTest { 57 58 @Mock 59 private ContentResolver mResolver; 60 61 private Context mContext; 62 private Intent mIntent; 63 private VolumeSeekBarPreferenceController mMediaController; 64 private VolumeSeekBarPreferenceController mRingController; 65 66 @Before setUp()67 public void setUp() { 68 MockitoAnnotations.initMocks(this); 69 mContext = spy(RuntimeEnvironment.application); 70 when(mContext.getContentResolver()).thenReturn(mResolver); 71 72 mMediaController = new MediaVolumePreferenceController(mContext); 73 mRingController = new RingVolumePreferenceController(mContext); 74 75 mIntent = createIntent(AudioManager.VOLUME_CHANGED_ACTION) 76 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 1) 77 .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 2) 78 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mMediaController.getAudioStream()); 79 } 80 81 @After cleanUp()82 public void cleanUp() { 83 ShadowSliceBroadcastRelay.reset(); 84 VolumeSliceHelper.sRegisteredUri.clear(); 85 VolumeSliceHelper.sIntentFilter = null; 86 } 87 88 @Test registerIntentToUri_volumeController_shouldRegisterReceiver()89 public void registerIntentToUri_volumeController_shouldRegisterReceiver() { 90 registerIntentToUri(mMediaController); 91 92 assertThat(ShadowSliceBroadcastRelay.getRegisteredCount()).isEqualTo(1); 93 assertThat(VolumeSliceHelper.sRegisteredUri) 94 .containsKey((mMediaController.getSliceUri())); 95 } 96 97 @Test registerIntentToUri_doubleVolumeControllers_shouldRegisterReceiverOnce()98 public void registerIntentToUri_doubleVolumeControllers_shouldRegisterReceiverOnce() { 99 registerIntentToUri(mMediaController); 100 101 registerIntentToUri(mRingController); 102 103 assertThat(ShadowSliceBroadcastRelay.getRegisteredCount()).isEqualTo(1); 104 assertThat(VolumeSliceHelper.sRegisteredUri) 105 .containsKey((mRingController.getSliceUri())); 106 } 107 108 @Test unregisterUri_notFinalUri_shouldNotUnregisterReceiver()109 public void unregisterUri_notFinalUri_shouldNotUnregisterReceiver() { 110 registerIntentToUri(mMediaController); 111 registerIntentToUri(mRingController); 112 113 VolumeSliceHelper.unregisterUri(mContext, mMediaController.getSliceUri()); 114 115 assertThat(ShadowSliceBroadcastRelay.getRegisteredCount()).isEqualTo(1); 116 assertThat(VolumeSliceHelper.sRegisteredUri) 117 .doesNotContainKey((mMediaController.getSliceUri())); 118 } 119 120 @Test unregisterUri_finalUri_shouldUnregisterReceiver()121 public void unregisterUri_finalUri_shouldUnregisterReceiver() { 122 registerIntentToUri(mMediaController); 123 124 VolumeSliceHelper.unregisterUri(mContext, mMediaController.getSliceUri()); 125 126 assertThat(ShadowSliceBroadcastRelay.getRegisteredCount()).isEqualTo(0); 127 assertThat(VolumeSliceHelper.sRegisteredUri) 128 .doesNotContainKey((mMediaController.getSliceUri())); 129 } 130 131 @Test unregisterUri_unregisterTwice_shouldUnregisterReceiverOnce()132 public void unregisterUri_unregisterTwice_shouldUnregisterReceiverOnce() { 133 registerIntentToUri(mMediaController); 134 135 VolumeSliceHelper.unregisterUri(mContext, mMediaController.getSliceUri()); 136 VolumeSliceHelper.unregisterUri(mContext, mMediaController.getSliceUri()); 137 138 assertThat(ShadowSliceBroadcastRelay.getRegisteredCount()).isEqualTo(0); 139 } 140 141 @Test unregisterUri_notRegistered_shouldNotUnregisterReceiver()142 public void unregisterUri_notRegistered_shouldNotUnregisterReceiver() { 143 registerIntentToUri(mMediaController); 144 145 VolumeSliceHelper.unregisterUri(mContext, mRingController.getSliceUri()); 146 147 assertThat(ShadowSliceBroadcastRelay.getRegisteredCount()).isEqualTo(1); 148 assertThat(VolumeSliceHelper.sRegisteredUri) 149 .containsKey((mMediaController.getSliceUri())); 150 } 151 152 @Test onReceive_audioStreamRegistered_shouldNotifyChange()153 public void onReceive_audioStreamRegistered_shouldNotifyChange() { 154 registerIntentToUri(mMediaController); 155 156 VolumeSliceHelper.onReceive(mContext, mIntent); 157 158 verify(mResolver).notifyChange(mMediaController.getSliceUri(), null); 159 } 160 161 @Test onReceive_audioStreamNotRegistered_shouldNotNotifyChange()162 public void onReceive_audioStreamNotRegistered_shouldNotNotifyChange() { 163 VolumeSliceHelper.onReceive(mContext, mIntent); 164 165 verify(mResolver, never()).notifyChange(mMediaController.getSliceUri(), null); 166 } 167 168 @Test onReceive_audioStreamNotMatched_shouldNotNotifyChange()169 public void onReceive_audioStreamNotMatched_shouldNotNotifyChange() { 170 registerIntentToUri(mMediaController); 171 mIntent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, AudioManager.STREAM_DTMF); 172 173 VolumeSliceHelper.onReceive(mContext, mIntent); 174 175 verify(mResolver, never()).notifyChange(mMediaController.getSliceUri(), null); 176 } 177 178 @Test onReceive_mediaVolumeNotChanged_shouldNotNotifyChange()179 public void onReceive_mediaVolumeNotChanged_shouldNotNotifyChange() { 180 mIntent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 1) 181 .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 1); 182 registerIntentToUri(mMediaController); 183 184 VolumeSliceHelper.onReceive(mContext, mIntent); 185 186 verify(mResolver, never()).notifyChange(mMediaController.getSliceUri(), null); 187 } 188 189 @Test onReceive_streamVolumeMuted_shouldNotifyChange()190 public void onReceive_streamVolumeMuted_shouldNotifyChange() { 191 final Intent intent = createIntent(AudioManager.STREAM_MUTE_CHANGED_ACTION) 192 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mMediaController.getAudioStream()); 193 registerIntentToUri(mMediaController); 194 registerIntentToUri(mRingController); 195 196 VolumeSliceHelper.onReceive(mContext, intent); 197 198 verify(mResolver).notifyChange(mMediaController.getSliceUri(), null); 199 } 200 201 @Test onReceive_streamDevicesChanged_shouldNotifyChange()202 public void onReceive_streamDevicesChanged_shouldNotifyChange() { 203 final Intent intent = createIntent(AudioManager.STREAM_DEVICES_CHANGED_ACTION) 204 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mRingController.getAudioStream()); 205 registerIntentToUri(mMediaController); 206 registerIntentToUri(mRingController); 207 208 VolumeSliceHelper.onReceive(mContext, intent); 209 210 verify(mResolver).notifyChange(mRingController.getSliceUri(), null); 211 } 212 213 @Test onReceive_primaryMutedChanged_shouldNotifyChangeAll()214 public void onReceive_primaryMutedChanged_shouldNotifyChangeAll() { 215 final Intent intent = createIntent(AudioManager.MASTER_MUTE_CHANGED_ACTION); 216 registerIntentToUri(mMediaController); 217 registerIntentToUri(mRingController); 218 219 VolumeSliceHelper.onReceive(mContext, intent); 220 221 verify(mResolver).notifyChange(mMediaController.getSliceUri(), null); 222 verify(mResolver).notifyChange(mRingController.getSliceUri(), null); 223 } 224 registerIntentToUri(VolumeSeekBarPreferenceController controller)225 private void registerIntentToUri(VolumeSeekBarPreferenceController controller) { 226 VolumeSliceHelper.registerIntentToUri(mContext, controller.getIntentFilter(), 227 controller.getSliceUri(), controller.getAudioStream()); 228 } 229 createIntent(String action)230 private Intent createIntent(String action) { 231 return new Intent(action) 232 .putExtra(SliceBroadcastRelay.EXTRA_URI, VOLUME_SLICES_URI.toString()); 233 } 234 235 @Implements(SliceBroadcastRelay.class) 236 public static class ShadowSliceBroadcastRelay { 237 238 private static int sRegisteredCount; 239 240 @Implementation registerReceiver(Context context, Uri sliceUri, Class<? extends BroadcastReceiver> receiver, IntentFilter filter)241 public static void registerReceiver(Context context, Uri sliceUri, 242 Class<? extends BroadcastReceiver> receiver, IntentFilter filter) { 243 sRegisteredCount++; 244 } 245 246 @Implementation unregisterReceivers(Context context, Uri sliceUri)247 public static void unregisterReceivers(Context context, Uri sliceUri) { 248 sRegisteredCount--; 249 } 250 251 @Resetter reset()252 static void reset() { 253 sRegisteredCount = 0; 254 } 255 getRegisteredCount()256 static int getRegisteredCount() { 257 return sRegisteredCount; 258 } 259 } 260 } 261