1 /* 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 package com.android.settings.bluetooth; 17 18 import static android.bluetooth.BluetoothDevice.PAIRING_VARIANT_CONSENT; 19 20 import static com.google.common.truth.Truth.assertThat; 21 22 import static org.mockito.Mockito.verify; 23 import static org.mockito.Mockito.when; 24 25 import android.bluetooth.BluetoothAdapter; 26 import android.bluetooth.BluetoothClass; 27 import android.bluetooth.BluetoothDevice; 28 import android.bluetooth.BluetoothProfile; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.os.Parcel; 32 33 import com.android.settings.core.SettingsUIDeviceConfig; 34 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; 35 import com.android.settings.testutils.shadow.ShadowBluetoothUtils; 36 import com.android.settings.testutils.shadow.ShadowDeviceConfig; 37 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 38 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; 39 import com.android.settingslib.bluetooth.LocalBluetoothManager; 40 import com.android.settingslib.bluetooth.LocalBluetoothProfile; 41 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; 42 43 import org.junit.Before; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.mockito.Mock; 47 import org.mockito.MockitoAnnotations; 48 import org.robolectric.RobolectricTestRunner; 49 import org.robolectric.RuntimeEnvironment; 50 import org.robolectric.annotation.Config; 51 import org.robolectric.shadow.api.Shadow; 52 53 import java.util.ArrayList; 54 import java.util.List; 55 56 @RunWith(RobolectricTestRunner.class) 57 @Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class, 58 ShadowDeviceConfig.class}) 59 public class BluetoothPairingControllerTest { 60 private final BluetoothClass mBluetoothClass = 61 createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE); 62 63 @Mock 64 private CachedBluetoothDeviceManager mCachedDeviceManager; 65 @Mock 66 private LocalBluetoothManager mLocalBluetoothManager; 67 @Mock 68 private LocalBluetoothProfileManager mLocalBluetoothProfileManager; 69 @Mock 70 private BluetoothDevice mBluetoothDevice; 71 @Mock 72 private CachedBluetoothDevice mCachedDevice; 73 @Mock 74 private LocalBluetoothProfile mLocalBluetoothProfile; 75 @Mock 76 private LocalBluetoothProfile mPbapLocalBluetoothProfile; 77 78 private Context mContext; 79 private BluetoothPairingController mBluetoothPairingController; 80 private ShadowBluetoothAdapter mShadowBluetoothAdapter; 81 createBtClass(int deviceClass)82 private BluetoothClass createBtClass(int deviceClass) { 83 Parcel p = Parcel.obtain(); 84 p.writeInt(deviceClass); 85 p.setDataPosition(0); // reset position of parcel before passing to constructor 86 87 BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p); 88 p.recycle(); 89 return bluetoothClass; 90 } 91 createBluetoothPairingController()92 private BluetoothPairingController createBluetoothPairingController() { 93 final Intent intent = new Intent(); 94 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice); 95 return new BluetoothPairingController(intent, mContext); 96 } 97 98 @Before setUp()99 public void setUp() { 100 MockitoAnnotations.initMocks(this); 101 102 mContext = RuntimeEnvironment.application; 103 mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); 104 mShadowBluetoothAdapter.setEnabled(true); 105 ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager; 106 mLocalBluetoothManager = Utils.getLocalBtManager(mContext); 107 when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); 108 when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); 109 when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice); 110 List<LocalBluetoothProfile> localBluetoothProfiles = new ArrayList<>(); 111 mockIsLeAudio(false); 112 localBluetoothProfiles.add(mLocalBluetoothProfile); 113 when(mCachedDevice.getProfiles()).thenReturn(localBluetoothProfiles); 114 when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice); 115 116 mBluetoothPairingController = createBluetoothPairingController(); 117 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 118 } 119 120 @Test onDialogPositiveClick_confirmationDialog_setPBAP()121 public void onDialogPositiveClick_confirmationDialog_setPBAP() { 122 mBluetoothPairingController.mType = PAIRING_VARIANT_CONSENT; 123 mBluetoothPairingController.onCheckedChanged(null, true); 124 125 mBluetoothPairingController.onDialogPositiveClick(null); 126 127 verify(mBluetoothDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); 128 } 129 130 @Test onSetContactSharingState_permissionAllowed_setPBAPAllowed()131 public void onSetContactSharingState_permissionAllowed_setPBAPAllowed() { 132 when(mBluetoothDevice.getPhonebookAccessPermission()).thenReturn( 133 BluetoothDevice.ACCESS_ALLOWED); 134 mBluetoothPairingController.setContactSharingState(); 135 mBluetoothPairingController.onDialogPositiveClick(null); 136 137 verify(mBluetoothDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); 138 } 139 140 @Test onSetContactSharingState_permissionUnknown_audioVideoHandsfree_setPBAPAllowed()141 public void onSetContactSharingState_permissionUnknown_audioVideoHandsfree_setPBAPAllowed() { 142 when(mBluetoothDevice.getPhonebookAccessPermission()).thenReturn( 143 BluetoothDevice.ACCESS_UNKNOWN); 144 when(mBluetoothDevice.getBluetoothClass()).thenReturn(mBluetoothClass); 145 mBluetoothPairingController.setContactSharingState(); 146 mBluetoothPairingController.onDialogPositiveClick(null); 147 148 verify(mBluetoothDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); 149 } 150 151 @Test onSetContactSharingState_permissionRejected_setPBAPRejected()152 public void onSetContactSharingState_permissionRejected_setPBAPRejected() { 153 when(mBluetoothDevice.getPhonebookAccessPermission()).thenReturn( 154 BluetoothDevice.ACCESS_REJECTED); 155 when(mBluetoothDevice.getBluetoothClass()).thenReturn(mBluetoothClass); 156 mBluetoothPairingController.setContactSharingState(); 157 mBluetoothPairingController.onDialogPositiveClick(null); 158 159 verify(mBluetoothDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED); 160 } 161 162 @Test isLeAudio_noLeProfile_returnsFalse()163 public void isLeAudio_noLeProfile_returnsFalse() { 164 mockIsLeAudio(false); 165 166 mBluetoothPairingController = createBluetoothPairingController(); 167 168 assertThat(mBluetoothPairingController.isLeAudio()).isFalse(); 169 } 170 171 @Test isLeAudio_isLeProfile_returnsTrue()172 public void isLeAudio_isLeProfile_returnsTrue() { 173 mockIsLeAudio(true); 174 175 mBluetoothPairingController = createBluetoothPairingController(); 176 177 assertThat(mBluetoothPairingController.isLeAudio()).isTrue(); 178 } 179 180 @Test isLeContactSharingEnabled_configIsFalse_returnsFalse()181 public void isLeContactSharingEnabled_configIsFalse_returnsFalse() { 182 mockIsLeContactSharingEnabled(false); 183 184 mBluetoothPairingController = createBluetoothPairingController(); 185 186 assertThat(mBluetoothPairingController.isLeContactSharingEnabled()).isFalse(); 187 } 188 189 @Test isLeContactSharingEnabled_configIsTrue_returnsTrue()190 public void isLeContactSharingEnabled_configIsTrue_returnsTrue() { 191 mockIsLeContactSharingEnabled(true); 192 193 mBluetoothPairingController = createBluetoothPairingController(); 194 195 assertThat(mBluetoothPairingController.isLeContactSharingEnabled()).isTrue(); 196 } 197 198 @Test isContactSharingVisible_profileIsNotReady_returnsTrue()199 public void isContactSharingVisible_profileIsNotReady_returnsTrue() { 200 // isProfileReady=false, isLeAudio=false, isLeContactSharingEnabled=true 201 mockIsProfileReady(false); 202 mockIsLeAudio(false); 203 mockIsLeContactSharingEnabled(true); 204 205 mBluetoothPairingController = createBluetoothPairingController(); 206 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 207 208 assertThat(mBluetoothPairingController.isContactSharingVisible()).isTrue(); 209 } 210 211 @Test isContactSharingVisible_profileIsReady_returnsFalse()212 public void isContactSharingVisible_profileIsReady_returnsFalse() { 213 // isProfileReady=true, isLeAudio=false, isLeContactSharingEnabled=true 214 mockIsProfileReady(true); 215 mockIsLeAudio(false); 216 mockIsLeContactSharingEnabled(true); 217 218 mBluetoothPairingController = createBluetoothPairingController(); 219 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 220 221 assertThat(mBluetoothPairingController.isContactSharingVisible()).isFalse(); 222 } 223 224 @Test isContactSharingVisible_DeviceIsLeAudioAndProfileIsReady_returnsFalse()225 public void isContactSharingVisible_DeviceIsLeAudioAndProfileIsReady_returnsFalse() { 226 // isProfileReady=true, isLeAudio=true, isLeContactSharingEnabled=true 227 mockIsProfileReady(true); 228 mockIsLeAudio(true); 229 mockIsLeContactSharingEnabled(true); 230 231 mBluetoothPairingController = createBluetoothPairingController(); 232 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 233 234 assertThat(mBluetoothPairingController.isContactSharingVisible()).isFalse(); 235 } 236 237 @Test isContactSharingVisible_DeviceIsLeAudioAndProfileIsNotReady_returnsTrue()238 public void isContactSharingVisible_DeviceIsLeAudioAndProfileIsNotReady_returnsTrue() { 239 // isProfileReady=false, isLeAudio=true, isLeContactSharingEnabled=true 240 mockIsProfileReady(false); 241 mockIsLeAudio(true); 242 mockIsLeContactSharingEnabled(true); 243 244 mBluetoothPairingController = createBluetoothPairingController(); 245 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 246 247 assertThat(mBluetoothPairingController.isContactSharingVisible()).isTrue(); 248 } 249 250 @Test isContactSharingVisible_DeviceIsLeAndContactSharingIsNotEnabled_returnsFalse()251 public void isContactSharingVisible_DeviceIsLeAndContactSharingIsNotEnabled_returnsFalse() { 252 // isProfileReady=false, isLeAudio=true, isLeContactSharingEnabled=false 253 mockIsProfileReady(false); 254 mockIsLeAudio(true); 255 mockIsLeContactSharingEnabled(false); 256 257 mBluetoothPairingController = createBluetoothPairingController(); 258 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 259 260 assertThat(mBluetoothPairingController.isContactSharingVisible()).isFalse(); 261 } 262 mockIsProfileReady(boolean mockValue)263 private void mockIsProfileReady(boolean mockValue) { 264 when(mPbapLocalBluetoothProfile.isProfileReady()).thenReturn(mockValue); 265 } 266 mockIsLeAudio(boolean mockValue)267 private void mockIsLeAudio(boolean mockValue) { 268 int profileId = BluetoothProfile.HEADSET; 269 if (mockValue) { 270 profileId = BluetoothProfile.LE_AUDIO; 271 } 272 when(mLocalBluetoothProfile.getProfileId()).thenReturn(profileId); 273 } 274 mockIsLeContactSharingEnabled(boolean mockValue)275 private void mockIsLeContactSharingEnabled(boolean mockValue) { 276 android.provider.DeviceConfig.setProperty( 277 android.provider.DeviceConfig.NAMESPACE_SETTINGS_UI, 278 SettingsUIDeviceConfig.BT_LE_AUDIO_CONTACT_SHARING_ENABLED, 279 /* value= */ mockValue ? "true" : "false", true); 280 } 281 } 282