1 /* 2 * Copyright (C) 2016 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.notification; 18 19 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_MEDIA_URI; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.Mockito.doReturn; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.when; 27 28 import android.app.PendingIntent; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.media.AudioManager; 32 import android.media.session.MediaController; 33 import android.net.Uri; 34 35 import androidx.slice.builders.SliceAction; 36 37 import com.android.settings.media.MediaOutputIndicatorWorker; 38 import com.android.settings.slices.SliceBackgroundWorker; 39 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 40 import com.android.settingslib.media.BluetoothMediaDevice; 41 import com.android.settingslib.media.MediaDevice; 42 import com.android.settingslib.media.MediaOutputConstants; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 import org.robolectric.RobolectricTestRunner; 50 import org.robolectric.RuntimeEnvironment; 51 import org.robolectric.annotation.Config; 52 import org.robolectric.annotation.Implementation; 53 import org.robolectric.annotation.Implements; 54 55 @RunWith(RobolectricTestRunner.class) 56 @Config(shadows = MediaVolumePreferenceControllerTest.ShadowSliceBackgroundWorker.class) 57 public class MediaVolumePreferenceControllerTest { 58 59 private static final String ACTION_LAUNCH_BROADCAST_DIALOG = 60 "android.settings.MEDIA_BROADCAST_DIALOG"; 61 private static MediaOutputIndicatorWorker sMediaOutputIndicatorWorker; 62 63 private MediaVolumePreferenceController mController; 64 65 private Context mContext; 66 67 @Mock 68 private MediaController mMediaController; 69 @Mock 70 private MediaDevice mDevice1; 71 @Mock 72 private MediaDevice mDevice2; 73 74 @Before setUp()75 public void setUp() { 76 MockitoAnnotations.initMocks(this); 77 78 mContext = RuntimeEnvironment.application; 79 mController = new MediaVolumePreferenceController(mContext); 80 sMediaOutputIndicatorWorker = spy( 81 new MediaOutputIndicatorWorker(mContext, VOLUME_MEDIA_URI)); 82 when(mDevice1.isBLEDevice()).thenReturn(true); 83 when(mDevice2.isBLEDevice()).thenReturn(false); 84 } 85 86 @Test isAvailable_byDefault_isTrue()87 public void isAvailable_byDefault_isTrue() { 88 assertThat(mController.isAvailable()).isTrue(); 89 } 90 91 @Test 92 @Config(qualifiers = "mcc999") isAvailable_whenNotVisible_isFalse()93 public void isAvailable_whenNotVisible_isFalse() { 94 assertThat(mController.isAvailable()).isFalse(); 95 } 96 97 @Test getAudioStream_shouldReturnMusic()98 public void getAudioStream_shouldReturnMusic() { 99 assertThat(mController.getAudioStream()).isEqualTo(AudioManager.STREAM_MUSIC); 100 } 101 102 @Test isSliceableCorrectKey_returnsTrue()103 public void isSliceableCorrectKey_returnsTrue() { 104 final MediaVolumePreferenceController controller = new MediaVolumePreferenceController( 105 mContext); 106 assertThat(controller.isSliceable()).isTrue(); 107 } 108 109 @Test isPublicSlice_returnTrue()110 public void isPublicSlice_returnTrue() { 111 assertThat(mController.isPublicSlice()).isTrue(); 112 } 113 114 @Test isSupportEndItem_withBleDevice_returnsTrue()115 public void isSupportEndItem_withBleDevice_returnsTrue() { 116 doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported(); 117 doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice(); 118 119 assertThat(mController.isSupportEndItem()).isTrue(); 120 } 121 122 @Test isSupportEndItem_notSupportedBroadcast_returnsFalse()123 public void isSupportEndItem_notSupportedBroadcast_returnsFalse() { 124 doReturn(false).when(sMediaOutputIndicatorWorker).isBroadcastSupported(); 125 doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice(); 126 127 assertThat(mController.isSupportEndItem()).isFalse(); 128 } 129 130 @Test isSupportEndItem_withNonBleDevice_returnsFalse()131 public void isSupportEndItem_withNonBleDevice_returnsFalse() { 132 doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported(); 133 doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice(); 134 135 assertThat(mController.isSupportEndItem()).isFalse(); 136 } 137 138 @Test getSliceEndItem_NotSupportEndItem_getsNullSliceAction()139 public void getSliceEndItem_NotSupportEndItem_getsNullSliceAction() { 140 doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported(); 141 doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice(); 142 143 final SliceAction sliceAction = mController.getSliceEndItem(mContext); 144 145 assertThat(sliceAction).isNull(); 146 } 147 148 @Test getSliceEndItem_deviceIsBroadcasting_getsBroadcastIntent()149 public void getSliceEndItem_deviceIsBroadcasting_getsBroadcastIntent() { 150 doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported(); 151 doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice(); 152 doReturn(true).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting(); 153 doReturn(mMediaController).when(sMediaOutputIndicatorWorker) 154 .getActiveLocalMediaController(); 155 156 final SliceAction sliceAction = mController.getSliceEndItem(mContext); 157 158 final PendingIntent endItemPendingIntent = sliceAction.getAction(); 159 final PendingIntent expectedToggleIntent = getBroadcastIntent( 160 MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG); 161 assertThat(endItemPendingIntent).isEqualTo(expectedToggleIntent); 162 } 163 164 @Test getSliceEndItem_deviceIsNotBroadcasting_getsActivityIntent()165 public void getSliceEndItem_deviceIsNotBroadcasting_getsActivityIntent() { 166 final MediaDevice device = mock(BluetoothMediaDevice.class); 167 final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class); 168 when(((BluetoothMediaDevice) device).getCachedDevice()).thenReturn(cachedDevice); 169 when(device.isBLEDevice()).thenReturn(true); 170 doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported(); 171 doReturn(device).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice(); 172 doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting(); 173 doReturn(mMediaController).when(sMediaOutputIndicatorWorker) 174 .getActiveLocalMediaController(); 175 176 final SliceAction sliceAction = mController.getSliceEndItem(mContext); 177 178 final PendingIntent endItemPendingIntent = sliceAction.getAction(); 179 final PendingIntent expectedPendingIntent = 180 getActivityIntent(ACTION_LAUNCH_BROADCAST_DIALOG); 181 assertThat(endItemPendingIntent).isEqualTo(expectedPendingIntent); 182 } 183 184 @Implements(SliceBackgroundWorker.class) 185 public static class ShadowSliceBackgroundWorker { 186 187 @Implementation getInstance(Uri uri)188 public static SliceBackgroundWorker getInstance(Uri uri) { 189 return sMediaOutputIndicatorWorker; 190 } 191 } 192 getBroadcastIntent(String action)193 private PendingIntent getBroadcastIntent(String action) { 194 final Intent intent = new Intent(action); 195 intent.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME); 196 return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent, 197 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); 198 } 199 getActivityIntent(String action)200 private PendingIntent getActivityIntent(String action) { 201 final Intent intent = new Intent(action); 202 return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 203 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); 204 } 205 } 206