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.testutils.shadow.ShadowBluetoothAdapter; 34 import com.android.settings.testutils.shadow.ShadowBluetoothUtils; 35 import com.android.settings.testutils.shadow.ShadowDeviceConfig; 36 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 37 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; 38 import com.android.settingslib.bluetooth.LocalBluetoothManager; 39 import com.android.settingslib.bluetooth.LocalBluetoothProfile; 40 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; 41 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.shadow.api.Shadow; 51 52 import java.util.ArrayList; 53 import java.util.List; 54 55 @RunWith(RobolectricTestRunner.class) 56 @Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class, 57 ShadowDeviceConfig.class}) 58 public class BluetoothPairingControllerTest { 59 private final BluetoothClass mBluetoothClass = 60 createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE); 61 62 @Mock 63 private CachedBluetoothDeviceManager mCachedDeviceManager; 64 @Mock 65 private LocalBluetoothManager mLocalBluetoothManager; 66 @Mock 67 private LocalBluetoothProfileManager mLocalBluetoothProfileManager; 68 @Mock 69 private BluetoothDevice mBluetoothDevice; 70 @Mock 71 private CachedBluetoothDevice mCachedDevice; 72 @Mock 73 private LocalBluetoothProfile mLocalBluetoothProfile; 74 @Mock 75 private LocalBluetoothProfile mPbapLocalBluetoothProfile; 76 77 private Context mContext; 78 private BluetoothPairingController mBluetoothPairingController; 79 private ShadowBluetoothAdapter mShadowBluetoothAdapter; 80 createBtClass(int deviceClass)81 private BluetoothClass createBtClass(int deviceClass) { 82 Parcel p = Parcel.obtain(); 83 p.writeInt(deviceClass); 84 p.setDataPosition(0); // reset position of parcel before passing to constructor 85 86 BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p); 87 p.recycle(); 88 return bluetoothClass; 89 } 90 createBluetoothPairingController()91 private BluetoothPairingController createBluetoothPairingController() { 92 final Intent intent = new Intent(); 93 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice); 94 return new BluetoothPairingController(intent, mContext); 95 } 96 97 @Before setUp()98 public void setUp() { 99 MockitoAnnotations.initMocks(this); 100 101 mContext = RuntimeEnvironment.application; 102 mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter()); 103 mShadowBluetoothAdapter.setEnabled(true); 104 ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager; 105 mLocalBluetoothManager = Utils.getLocalBtManager(mContext); 106 when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); 107 when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); 108 when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice); 109 List<LocalBluetoothProfile> localBluetoothProfiles = new ArrayList<>(); 110 mockIsLeAudio(false); 111 localBluetoothProfiles.add(mLocalBluetoothProfile); 112 when(mCachedDevice.getProfiles()).thenReturn(localBluetoothProfiles); 113 when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice); 114 115 mBluetoothPairingController = createBluetoothPairingController(); 116 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 117 } 118 119 @Test onDialogPositiveClick_confirmationDialog_setPBAP()120 public void onDialogPositiveClick_confirmationDialog_setPBAP() { 121 mBluetoothPairingController.mType = PAIRING_VARIANT_CONSENT; 122 mBluetoothPairingController.onCheckedChanged(null, true); 123 124 mBluetoothPairingController.onDialogPositiveClick(null); 125 126 verify(mBluetoothDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); 127 } 128 129 @Test onSetContactSharingState_permissionAllowed_setPBAPAllowed()130 public void onSetContactSharingState_permissionAllowed_setPBAPAllowed() { 131 when(mBluetoothDevice.getPhonebookAccessPermission()).thenReturn( 132 BluetoothDevice.ACCESS_ALLOWED); 133 mBluetoothPairingController.setContactSharingState(); 134 mBluetoothPairingController.onDialogPositiveClick(null); 135 136 verify(mBluetoothDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); 137 } 138 139 @Test onSetContactSharingState_permissionUnknown_audioVideoHandsfree_setPBAPAllowed()140 public void onSetContactSharingState_permissionUnknown_audioVideoHandsfree_setPBAPAllowed() { 141 when(mBluetoothDevice.getPhonebookAccessPermission()).thenReturn( 142 BluetoothDevice.ACCESS_UNKNOWN); 143 when(mBluetoothDevice.getBluetoothClass()).thenReturn(mBluetoothClass); 144 mBluetoothPairingController.setContactSharingState(); 145 mBluetoothPairingController.onDialogPositiveClick(null); 146 147 verify(mBluetoothDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); 148 } 149 150 @Test onSetContactSharingState_permissionRejected_setPBAPRejected()151 public void onSetContactSharingState_permissionRejected_setPBAPRejected() { 152 when(mBluetoothDevice.getPhonebookAccessPermission()).thenReturn( 153 BluetoothDevice.ACCESS_REJECTED); 154 when(mBluetoothDevice.getBluetoothClass()).thenReturn(mBluetoothClass); 155 mBluetoothPairingController.setContactSharingState(); 156 mBluetoothPairingController.onDialogPositiveClick(null); 157 158 verify(mBluetoothDevice).setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED); 159 } 160 161 @Test isLeAudio_noLeProfile_returnsFalse()162 public void isLeAudio_noLeProfile_returnsFalse() { 163 mockIsLeAudio(false); 164 165 mBluetoothPairingController = createBluetoothPairingController(); 166 167 assertThat(mBluetoothPairingController.isLeAudio()).isFalse(); 168 } 169 170 @Test isLeAudio_isLeProfile_returnsTrue()171 public void isLeAudio_isLeProfile_returnsTrue() { 172 mockIsLeAudio(true); 173 174 mBluetoothPairingController = createBluetoothPairingController(); 175 176 assertThat(mBluetoothPairingController.isLeAudio()).isTrue(); 177 } 178 179 @Test isContactSharingVisible_profileIsNotReady_returnsTrue()180 public void isContactSharingVisible_profileIsNotReady_returnsTrue() { 181 // isProfileReady=false, isLeAudio=false 182 mockIsProfileReady(false); 183 mockIsLeAudio(false); 184 185 mBluetoothPairingController = createBluetoothPairingController(); 186 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 187 188 assertThat(mBluetoothPairingController.isContactSharingVisible()).isTrue(); 189 } 190 191 @Test isContactSharingVisible_profileIsReady_returnsFalse()192 public void isContactSharingVisible_profileIsReady_returnsFalse() { 193 // isProfileReady=true, isLeAudio=false 194 mockIsProfileReady(true); 195 mockIsLeAudio(false); 196 197 mBluetoothPairingController = createBluetoothPairingController(); 198 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 199 200 assertThat(mBluetoothPairingController.isContactSharingVisible()).isFalse(); 201 } 202 203 @Test isContactSharingVisible_DeviceIsLeAudioAndProfileIsReady_returnsFalse()204 public void isContactSharingVisible_DeviceIsLeAudioAndProfileIsReady_returnsFalse() { 205 // isProfileReady=true, isLeAudio=true 206 mockIsProfileReady(true); 207 mockIsLeAudio(true); 208 209 mBluetoothPairingController = createBluetoothPairingController(); 210 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 211 212 assertThat(mBluetoothPairingController.isContactSharingVisible()).isFalse(); 213 } 214 215 @Test isContactSharingVisible_DeviceIsLeAudioAndProfileIsNotReady_returnsTrue()216 public void isContactSharingVisible_DeviceIsLeAudioAndProfileIsNotReady_returnsTrue() { 217 // isProfileReady=false, isLeAudio=true 218 mockIsProfileReady(false); 219 mockIsLeAudio(true); 220 221 mBluetoothPairingController = createBluetoothPairingController(); 222 mBluetoothPairingController.mockPbapClientProfile(mPbapLocalBluetoothProfile); 223 224 assertThat(mBluetoothPairingController.isContactSharingVisible()).isTrue(); 225 } 226 mockIsProfileReady(boolean mockValue)227 private void mockIsProfileReady(boolean mockValue) { 228 when(mPbapLocalBluetoothProfile.isProfileReady()).thenReturn(mockValue); 229 } 230 mockIsLeAudio(boolean mockValue)231 private void mockIsLeAudio(boolean mockValue) { 232 int profileId = BluetoothProfile.HEADSET; 233 if (mockValue) { 234 profileId = BluetoothProfile.LE_AUDIO; 235 } 236 when(mLocalBluetoothProfile.getProfileId()).thenReturn(profileId); 237 } 238 } 239