1 /* 2 * Copyright 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 package com.android.settings.connecteddevice; 17 18 import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; 19 import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.ArgumentMatchers.anyString; 25 import static org.mockito.Mockito.doReturn; 26 import static org.mockito.Mockito.spy; 27 import static org.mockito.Mockito.verify; 28 import static org.mockito.Mockito.when; 29 30 import android.bluetooth.BluetoothProfile; 31 import android.content.Context; 32 import android.content.pm.PackageManager; 33 import android.media.AudioManager; 34 35 import androidx.appcompat.app.AlertDialog; 36 import androidx.fragment.app.FragmentActivity; 37 import androidx.preference.Preference; 38 import androidx.preference.PreferenceGroup; 39 import androidx.preference.PreferenceManager; 40 import androidx.preference.PreferenceScreen; 41 42 import com.android.settings.R; 43 import com.android.settings.bluetooth.AvailableMediaBluetoothDeviceUpdater; 44 import com.android.settings.bluetooth.Utils; 45 import com.android.settings.dashboard.DashboardFragment; 46 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; 47 import com.android.settings.testutils.shadow.ShadowAudioManager; 48 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; 49 import com.android.settings.testutils.shadow.ShadowBluetoothUtils; 50 import com.android.settingslib.bluetooth.BluetoothCallback; 51 import com.android.settingslib.bluetooth.BluetoothEventManager; 52 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 53 import com.android.settingslib.bluetooth.HearingAidProfile; 54 import com.android.settingslib.bluetooth.LocalBluetoothManager; 55 56 import org.junit.Before; 57 import org.junit.Test; 58 import org.junit.runner.RunWith; 59 import org.mockito.Answers; 60 import org.mockito.Mock; 61 import org.mockito.MockitoAnnotations; 62 import org.robolectric.Robolectric; 63 import org.robolectric.RobolectricTestRunner; 64 import org.robolectric.RuntimeEnvironment; 65 import org.robolectric.annotation.Config; 66 67 /** Tests for {@link AvailableMediaDeviceGroupController}. */ 68 @RunWith(RobolectricTestRunner.class) 69 @Config(shadows = {ShadowAudioManager.class, ShadowBluetoothAdapter.class, 70 ShadowBluetoothUtils.class}) 71 public class AvailableMediaDeviceGroupControllerTest { 72 73 private static final String PREFERENCE_KEY_1 = "pref_key_1"; 74 75 @Mock 76 private DashboardFragment mDashboardFragment; 77 @Mock 78 private AvailableMediaBluetoothDeviceUpdater mAvailableMediaBluetoothDeviceUpdater; 79 @Mock 80 private PreferenceScreen mPreferenceScreen; 81 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 82 private PreferenceManager mPreferenceManager; 83 @Mock 84 private PackageManager mPackageManager; 85 @Mock 86 private BluetoothEventManager mEventManager; 87 @Mock 88 private LocalBluetoothManager mLocalManager; 89 @Mock 90 private CachedBluetoothDevice mCachedBluetoothDevice; 91 92 private PreferenceGroup mPreferenceGroup; 93 private Context mContext; 94 private Preference mPreference; 95 private AvailableMediaDeviceGroupController mAvailableMediaDeviceGroupController; 96 private LocalBluetoothManager mLocalBluetoothManager; 97 private AudioManager mAudioManager; 98 99 @Before setUp()100 public void setUp() { 101 MockitoAnnotations.initMocks(this); 102 103 mContext = spy(RuntimeEnvironment.application); 104 mPreference = new Preference(mContext); 105 mPreference.setKey(PREFERENCE_KEY_1); 106 mPreferenceGroup = spy(new PreferenceScreen(mContext, null)); 107 final FragmentActivity mActivity = Robolectric.setupActivity(FragmentActivity.class); 108 when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager); 109 doReturn(mContext).when(mDashboardFragment).getContext(); 110 doReturn(mPackageManager).when(mContext).getPackageManager(); 111 doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); 112 when(mDashboardFragment.getParentFragmentManager()).thenReturn( 113 mActivity.getSupportFragmentManager()); 114 115 ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager; 116 mLocalBluetoothManager = Utils.getLocalBtManager(mContext); 117 mAudioManager = mContext.getSystemService(AudioManager.class); 118 doReturn(mEventManager).when(mLocalBluetoothManager).getEventManager(); 119 120 mAvailableMediaDeviceGroupController = spy( 121 new AvailableMediaDeviceGroupController(mContext)); 122 mAvailableMediaDeviceGroupController. 123 setBluetoothDeviceUpdater(mAvailableMediaBluetoothDeviceUpdater); 124 mAvailableMediaDeviceGroupController.mPreferenceGroup = mPreferenceGroup; 125 } 126 127 @Test onDeviceAdded_firstAdd_becomeVisibleAndPreferenceAdded()128 public void onDeviceAdded_firstAdd_becomeVisibleAndPreferenceAdded() { 129 mAvailableMediaDeviceGroupController.onDeviceAdded(mPreference); 130 131 assertThat(mPreferenceGroup.isVisible()).isTrue(); 132 assertThat((Preference) mPreferenceGroup.findPreference(PREFERENCE_KEY_1)) 133 .isEqualTo(mPreference); 134 } 135 136 @Test onDeviceRemoved_lastRemove_becomeInvisibleAndPreferenceRemoved()137 public void onDeviceRemoved_lastRemove_becomeInvisibleAndPreferenceRemoved() { 138 mPreferenceGroup.addPreference(mPreference); 139 140 mAvailableMediaDeviceGroupController.onDeviceRemoved(mPreference); 141 142 assertThat(mPreferenceGroup.isVisible()).isFalse(); 143 assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0); 144 } 145 146 @Test onDeviceRemoved_notLastRemove_stillVisible()147 public void onDeviceRemoved_notLastRemove_stillVisible() { 148 mPreferenceGroup.setVisible(true); 149 mPreferenceGroup.addPreference(mPreference); 150 mPreferenceGroup.addPreference(new Preference(mContext)); 151 152 mAvailableMediaDeviceGroupController.onDeviceRemoved(mPreference); 153 154 assertThat(mPreferenceGroup.isVisible()).isTrue(); 155 } 156 157 @Test displayPreference_becomeInvisible()158 public void displayPreference_becomeInvisible() { 159 doReturn(mPreferenceGroup).when(mPreferenceScreen).findPreference(anyString()); 160 161 mAvailableMediaDeviceGroupController.displayPreference(mPreferenceScreen); 162 163 assertThat(mPreferenceGroup.isVisible()).isFalse(); 164 } 165 166 @Test testRegister()167 public void testRegister() { 168 // register the callback in onStart() 169 mAvailableMediaDeviceGroupController.onStart(); 170 171 verify(mAvailableMediaBluetoothDeviceUpdater).registerCallback(); 172 verify(mLocalBluetoothManager.getEventManager()).registerCallback( 173 any(BluetoothCallback.class)); 174 verify(mAvailableMediaBluetoothDeviceUpdater).refreshPreference(); 175 } 176 177 @Test testUnregister()178 public void testUnregister() { 179 // unregister the callback in onStop() 180 mAvailableMediaDeviceGroupController.onStop(); 181 verify(mAvailableMediaBluetoothDeviceUpdater).unregisterCallback(); 182 verify(mLocalBluetoothManager.getEventManager()).unregisterCallback( 183 any(BluetoothCallback.class)); 184 } 185 186 @Test testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported()187 public void testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported() { 188 doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); 189 190 assertThat(mAvailableMediaDeviceGroupController.getAvailabilityStatus()).isEqualTo( 191 UNSUPPORTED_ON_DEVICE); 192 } 193 194 @Test testGetAvailabilityStatus_BluetoothFeature_returnSupported()195 public void testGetAvailabilityStatus_BluetoothFeature_returnSupported() { 196 doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); 197 198 assertThat(mAvailableMediaDeviceGroupController.getAvailabilityStatus()).isEqualTo( 199 AVAILABLE_UNSEARCHABLE); 200 } 201 202 @Test setTitle_inCallState_showCallStateTitle()203 public void setTitle_inCallState_showCallStateTitle() { 204 mAudioManager.setMode(AudioManager.MODE_IN_CALL); 205 mAvailableMediaDeviceGroupController.onAudioModeChanged(); 206 207 assertThat(mPreferenceGroup.getTitle()).isEqualTo( 208 mContext.getText(R.string.connected_device_call_device_title)); 209 } 210 211 @Test setTitle_notInCallState_showMediaStateTitle()212 public void setTitle_notInCallState_showMediaStateTitle() { 213 mAudioManager.setMode(AudioManager.MODE_NORMAL); 214 mAvailableMediaDeviceGroupController.onAudioModeChanged(); 215 216 assertThat(mPreferenceGroup.getTitle()).isEqualTo( 217 mContext.getText(R.string.connected_device_media_device_title)); 218 } 219 220 @Test onStart_localBluetoothManagerNull_shouldNotCrash()221 public void onStart_localBluetoothManagerNull_shouldNotCrash() { 222 mAvailableMediaDeviceGroupController.mLocalBluetoothManager = null; 223 224 // Shouldn't crash 225 mAvailableMediaDeviceGroupController.onStart(); 226 } 227 228 @Test onStop_localBluetoothManagerNull_shouldNotCrash()229 public void onStop_localBluetoothManagerNull_shouldNotCrash() { 230 mAvailableMediaDeviceGroupController.mLocalBluetoothManager = null; 231 232 // Shouldn't crash 233 mAvailableMediaDeviceGroupController.onStop(); 234 } 235 236 @Test 237 @Config(shadows = ShadowAlertDialogCompat.class) onActiveDeviceChanged_hearingAidProfile_launchHearingAidPairingDialog()238 public void onActiveDeviceChanged_hearingAidProfile_launchHearingAidPairingDialog() { 239 when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true); 240 when(mCachedBluetoothDevice.getDeviceMode()).thenReturn( 241 HearingAidProfile.DeviceMode.MODE_BINAURAL); 242 when(mCachedBluetoothDevice.getDeviceSide()).thenReturn( 243 HearingAidProfile.DeviceSide.SIDE_LEFT); 244 mAvailableMediaDeviceGroupController.init(mDashboardFragment); 245 246 mAvailableMediaDeviceGroupController.onActiveDeviceChanged(mCachedBluetoothDevice, 247 BluetoothProfile.HEARING_AID); 248 249 final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); 250 assertThat(dialog.isShowing()).isTrue(); 251 } 252 } 253