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 17 package com.android.settings.accessibility; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.doReturn; 22 import static org.mockito.Mockito.spy; 23 import static org.mockito.Mockito.when; 24 import static org.robolectric.Shadows.shadowOf; 25 26 import android.app.Application; 27 import android.bluetooth.BluetoothAdapter; 28 import android.bluetooth.BluetoothDevice; 29 import android.bluetooth.BluetoothHapClient; 30 import android.bluetooth.BluetoothHearingAid; 31 import android.bluetooth.BluetoothProfile; 32 import android.content.BroadcastReceiver; 33 import android.content.Context; 34 import android.content.Intent; 35 36 import androidx.preference.Preference; 37 import androidx.test.core.app.ApplicationProvider; 38 39 import com.android.settings.R; 40 import com.android.settings.bluetooth.Utils; 41 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; 42 import com.android.settings.testutils.shadow.ShadowBluetoothUtils; 43 import com.android.settingslib.bluetooth.BluetoothEventManager; 44 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 45 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; 46 import com.android.settingslib.bluetooth.HapClientProfile; 47 import com.android.settingslib.bluetooth.HearingAidInfo; 48 import com.android.settingslib.bluetooth.HearingAidProfile; 49 import com.android.settingslib.bluetooth.LocalBluetoothManager; 50 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; 51 52 import org.junit.After; 53 import org.junit.Before; 54 import org.junit.Rule; 55 import org.junit.Test; 56 import org.junit.runner.RunWith; 57 import org.mockito.Mock; 58 import org.mockito.junit.MockitoJUnit; 59 import org.mockito.junit.MockitoRule; 60 import org.robolectric.RobolectricTestRunner; 61 import org.robolectric.annotation.Config; 62 import org.robolectric.shadow.api.Shadow; 63 import org.robolectric.shadows.ShadowApplication; 64 import org.robolectric.shadows.ShadowLooper; 65 66 import java.util.ArrayList; 67 import java.util.HashSet; 68 import java.util.List; 69 import java.util.Set; 70 71 /** Tests for {@link AccessibilityHearingAidPreferenceController}. */ 72 @RunWith(RobolectricTestRunner.class) 73 @Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class}) 74 public class AccessibilityHearingAidPreferenceControllerTest { 75 @Rule 76 public final MockitoRule mockito = MockitoJUnit.rule(); 77 78 private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1"; 79 private static final String TEST_DEVICE_ADDRESS_2 = "00:A2:A2:A2:A2:A2"; 80 private static final String TEST_DEVICE_NAME = "TEST_HEARING_AID_BT_DEVICE_NAME"; 81 private static final String HEARING_AID_PREFERENCE = "hearing_aid_preference"; 82 83 private BluetoothAdapter mBluetoothAdapter; 84 private ShadowBluetoothAdapter mShadowBluetoothAdapter; 85 private BluetoothDevice mBluetoothDevice; 86 87 private BluetoothDevice mSubBluetoothDevice; 88 private final Context mContext = ApplicationProvider.getApplicationContext(); 89 90 private Preference mHearingAidPreference; 91 private AccessibilityHearingAidPreferenceController mPreferenceController; 92 private ShadowApplication mShadowApplication; 93 94 @Mock 95 private CachedBluetoothDevice mCachedBluetoothDevice; 96 @Mock 97 private CachedBluetoothDevice mCachedSubBluetoothDevice; 98 @Mock 99 private CachedBluetoothDeviceManager mCachedDeviceManager; 100 @Mock 101 private LocalBluetoothManager mLocalBluetoothManager; 102 @Mock 103 private BluetoothEventManager mEventManager; 104 @Mock 105 private LocalBluetoothProfileManager mLocalBluetoothProfileManager; 106 @Mock 107 private HearingAidProfile mHearingAidProfile; 108 @Mock 109 private HapClientProfile mHapClientProfile; 110 111 @Before setUp()112 public void setUp() { 113 mShadowApplication = shadowOf((Application) ApplicationProvider.getApplicationContext()); 114 setupEnvironment(); 115 116 mHearingAidPreference = new Preference(mContext); 117 mHearingAidPreference.setKey(HEARING_AID_PREFERENCE); 118 mPreferenceController = new AccessibilityHearingAidPreferenceController(mContext, 119 HEARING_AID_PREFERENCE); 120 mPreferenceController.setPreference(mHearingAidPreference); 121 mHearingAidPreference.setSummary(""); 122 } 123 124 @After tearDown()125 public void tearDown() { 126 ShadowBluetoothUtils.reset(); 127 } 128 129 @Test getSummary_connectedAshaHearingAidRightSide_connectedRightSideSummary()130 public void getSummary_connectedAshaHearingAidRightSide_connectedRightSideSummary() { 131 when(mCachedBluetoothDevice.getDeviceSide()).thenReturn( 132 HearingAidInfo.DeviceSide.SIDE_RIGHT); 133 when(mHearingAidProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList()); 134 135 mPreferenceController.onStart(); 136 Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); 137 intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHearingAid.STATE_CONNECTED); 138 sendIntent(intent); 139 ShadowLooper.idleMainLooper(); 140 141 assertThat(mHearingAidPreference.getSummary().toString().contentEquals( 142 "TEST_HEARING_AID_BT_DEVICE_NAME / Right only")).isTrue(); 143 } 144 145 @Test getSummary_connectedAshaHearingAidBothSide_connectedBothSideSummary()146 public void getSummary_connectedAshaHearingAidBothSide_connectedBothSideSummary() { 147 when(mCachedBluetoothDevice.getDeviceSide()).thenReturn( 148 HearingAidInfo.DeviceSide.SIDE_LEFT); 149 when(mCachedBluetoothDevice.getSubDevice()).thenReturn(mCachedSubBluetoothDevice); 150 when(mSubBluetoothDevice.isConnected()).thenReturn(true); 151 when(mHearingAidProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList()); 152 153 mPreferenceController.onStart(); 154 Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); 155 intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHearingAid.STATE_CONNECTED); 156 sendIntent(intent); 157 ShadowLooper.idleMainLooper(); 158 159 assertThat(mHearingAidPreference.getSummary().toString().contentEquals( 160 "TEST_HEARING_AID_BT_DEVICE_NAME / Left and right")).isTrue(); 161 } 162 163 @Test getSummary_connectedLeAudioHearingAidLeftSide_connectedLeftSideSummary()164 public void getSummary_connectedLeAudioHearingAidLeftSide_connectedLeftSideSummary() { 165 when(mCachedBluetoothDevice.getDeviceSide()).thenReturn( 166 HearingAidInfo.DeviceSide.SIDE_LEFT); 167 when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(new HashSet<>()); 168 when(mHapClientProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList()); 169 170 mPreferenceController.onStart(); 171 Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED); 172 intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHapClient.STATE_CONNECTED); 173 sendIntent(intent); 174 ShadowLooper.idleMainLooper(); 175 176 assertThat(mHearingAidPreference.getSummary().toString().contentEquals( 177 "TEST_HEARING_AID_BT_DEVICE_NAME / Left only")).isTrue(); 178 } 179 180 @Test getSummary_connectedLeAudioHearingAidRightSide_connectedRightSideSummary()181 public void getSummary_connectedLeAudioHearingAidRightSide_connectedRightSideSummary() { 182 when(mCachedBluetoothDevice.getDeviceSide()).thenReturn( 183 HearingAidInfo.DeviceSide.SIDE_RIGHT); 184 when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(new HashSet<>()); 185 when(mHapClientProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList()); 186 187 mPreferenceController.onStart(); 188 Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED); 189 intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHapClient.STATE_CONNECTED); 190 sendIntent(intent); 191 ShadowLooper.idleMainLooper(); 192 193 assertThat(mHearingAidPreference.getSummary().toString().contentEquals( 194 "TEST_HEARING_AID_BT_DEVICE_NAME / Right only")).isTrue(); 195 } 196 197 @Test getSummary_connectedLeAudioHearingAidLeftAndRightSide_connectedSummary()198 public void getSummary_connectedLeAudioHearingAidLeftAndRightSide_connectedSummary() { 199 when(mCachedBluetoothDevice.getDeviceSide()).thenReturn( 200 HearingAidInfo.DeviceSide.SIDE_LEFT_AND_RIGHT); 201 when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(new HashSet<>()); 202 when(mHapClientProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList()); 203 204 mPreferenceController.onStart(); 205 Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED); 206 intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHapClient.STATE_CONNECTED); 207 sendIntent(intent); 208 ShadowLooper.idleMainLooper(); 209 210 assertThat(mHearingAidPreference.getSummary().toString().contentEquals( 211 "TEST_HEARING_AID_BT_DEVICE_NAME / Left and right")).isTrue(); 212 } 213 214 @Test getSummary_connectedLeAudioHearingAidBothSide_connectedBothSideSummary()215 public void getSummary_connectedLeAudioHearingAidBothSide_connectedBothSideSummary() { 216 when(mCachedBluetoothDevice.getMemberDevice()).thenReturn(generateMemberDevices()); 217 when(mHapClientProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList()); 218 when(mSubBluetoothDevice.isConnected()).thenReturn(true); 219 220 mPreferenceController.onStart(); 221 Intent intent = new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED); 222 intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHapClient.STATE_CONNECTED); 223 sendIntent(intent); 224 ShadowLooper.idleMainLooper(); 225 226 assertThat(mHearingAidPreference.getSummary().toString()).isEqualTo( 227 "TEST_HEARING_AID_BT_DEVICE_NAME / Left and right"); 228 } 229 230 @Test getSummary_connectedMultipleHearingAids_connectedMultipleDevicesSummary()231 public void getSummary_connectedMultipleHearingAids_connectedMultipleDevicesSummary() { 232 when(mCachedBluetoothDevice.getDeviceSide()).thenReturn( 233 HearingAidInfo.DeviceSide.SIDE_LEFT); 234 when(mHearingAidProfile.getConnectedDevices()).thenReturn( 235 generateMultipleHearingAidDeviceList()); 236 237 mPreferenceController.onStart(); 238 Intent intent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); 239 intent.putExtra(BluetoothHearingAid.EXTRA_STATE, BluetoothHearingAid.STATE_CONNECTED); 240 sendIntent(intent); 241 ShadowLooper.idleMainLooper(); 242 243 assertThat(mHearingAidPreference.getSummary().toString().contentEquals( 244 "TEST_HEARING_AID_BT_DEVICE_NAME +1 more")).isTrue(); 245 } 246 247 @Test getSummary_bluetoothOff_disconnectedSummary()248 public void getSummary_bluetoothOff_disconnectedSummary() { 249 mPreferenceController.onStart(); 250 Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); 251 intent.putExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF); 252 sendIntent(intent); 253 ShadowLooper.idleMainLooper(); 254 255 assertThat(mHearingAidPreference.getSummary()).isEqualTo( 256 mContext.getText(R.string.accessibility_hearingaid_not_connected_summary)); 257 } 258 259 @Test onServiceConnected_onHearingAidProfileConnected_updateSummary()260 public void onServiceConnected_onHearingAidProfileConnected_updateSummary() { 261 when(mCachedBluetoothDevice.getDeviceSide()).thenReturn( 262 HearingAidInfo.DeviceSide.SIDE_LEFT); 263 when(mHearingAidProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList()); 264 265 mPreferenceController.onStart(); 266 mPreferenceController.onServiceConnected(); 267 ShadowLooper.idleMainLooper(); 268 269 assertThat(mHearingAidPreference.getSummary().toString()).isEqualTo( 270 "TEST_HEARING_AID_BT_DEVICE_NAME / Left only"); 271 } 272 273 @Test onServiceConnected_onHapClientProfileConnected_updateSummary()274 public void onServiceConnected_onHapClientProfileConnected_updateSummary() { 275 when(mCachedBluetoothDevice.getDeviceSide()).thenReturn( 276 HearingAidInfo.DeviceSide.SIDE_RIGHT); 277 when(mHapClientProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList()); 278 279 mPreferenceController.onStart(); 280 mPreferenceController.onServiceConnected(); 281 ShadowLooper.idleMainLooper(); 282 283 assertThat(mHearingAidPreference.getSummary().toString()).isEqualTo( 284 "TEST_HEARING_AID_BT_DEVICE_NAME / Right only"); 285 } 286 setupEnvironment()287 private void setupEnvironment() { 288 ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager; 289 mLocalBluetoothManager = Utils.getLocalBtManager(mContext); 290 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 291 mShadowBluetoothAdapter = Shadow.extract(mBluetoothAdapter); 292 mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HEARING_AID); 293 mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HAP_CLIENT); 294 mBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS)); 295 mSubBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2)); 296 mBluetoothAdapter.enable(); 297 298 doReturn(mEventManager).when(mLocalBluetoothManager).getEventManager(); 299 when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); 300 when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); 301 when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); 302 when(mLocalBluetoothProfileManager.getHapClientProfile()).thenReturn(mHapClientProfile); 303 when(mHearingAidProfile.isProfileReady()).thenReturn(true); 304 when(mHapClientProfile.isProfileReady()).thenReturn(true); 305 when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice); 306 when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); 307 when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS); 308 when(mCachedBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME); 309 when(mCachedDeviceManager.findDevice(mSubBluetoothDevice)).thenReturn( 310 mCachedSubBluetoothDevice); 311 when(mCachedSubBluetoothDevice.getDevice()).thenReturn(mSubBluetoothDevice); 312 } 313 sendIntent(Intent intent)314 private void sendIntent(Intent intent) { 315 for (BroadcastReceiver receiver : mShadowApplication.getReceiversForIntent(intent)) { 316 receiver.onReceive(mContext, intent); 317 } 318 } 319 generateHearingAidDeviceList()320 private List<BluetoothDevice> generateHearingAidDeviceList() { 321 final List<BluetoothDevice> deviceList = new ArrayList<>(1); 322 deviceList.add(mBluetoothDevice); 323 return deviceList; 324 } 325 generateMultipleHearingAidDeviceList()326 private List<BluetoothDevice> generateMultipleHearingAidDeviceList() { 327 // Generates different Bluetooth devices for testing multiple devices 328 final List<BluetoothDevice> deviceList = new ArrayList<>(2); 329 deviceList.add(mBluetoothDevice); 330 deviceList.add(mSubBluetoothDevice); 331 return deviceList; 332 } 333 generateMemberDevices()334 private Set<CachedBluetoothDevice> generateMemberDevices() { 335 final Set<CachedBluetoothDevice> memberDevices = new HashSet<>(); 336 memberDevices.add(mCachedSubBluetoothDevice); 337 return memberDevices; 338 } 339 } 340