1 /* 2 * Copyright (C) 2023 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.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.ArgumentMatchers.isNull; 24 import static org.mockito.Mockito.doReturn; 25 import static org.mockito.Mockito.never; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.when; 28 29 import android.bluetooth.BluetoothDevice; 30 import android.content.Context; 31 import android.media.AudioAttributes; 32 import android.media.AudioDeviceAttributes; 33 import android.media.AudioDeviceInfo; 34 import android.media.AudioManager; 35 import android.media.audiopolicy.AudioProductStrategy; 36 37 import androidx.preference.ListPreference; 38 import androidx.test.core.app.ApplicationProvider; 39 40 import com.android.settings.R; 41 import com.android.settings.bluetooth.Utils; 42 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; 43 import com.android.settings.testutils.shadow.ShadowBluetoothUtils; 44 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 45 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; 46 import com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants; 47 import com.android.settingslib.bluetooth.HearingAidAudioRoutingHelper; 48 import com.android.settingslib.bluetooth.LocalBluetoothManager; 49 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; 50 51 import org.junit.Before; 52 import org.junit.Rule; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.Mock; 56 import org.mockito.Spy; 57 import org.mockito.junit.MockitoJUnit; 58 import org.mockito.junit.MockitoRule; 59 import org.robolectric.RobolectricTestRunner; 60 import org.robolectric.annotation.Config; 61 62 import java.util.List; 63 64 /** Tests for {@link HearingDeviceAudioRoutingBasePreferenceController}. */ 65 @RunWith(RobolectricTestRunner.class) 66 @Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class}) 67 public class HearingDeviceAudioRoutingBasePreferenceControllerTest { 68 69 @Rule 70 public MockitoRule mMockitoRule = MockitoJUnit.rule(); 71 72 @Spy 73 private final Context mContext = ApplicationProvider.getApplicationContext(); 74 private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1"; 75 private final ListPreference mListPreference = new ListPreference(mContext); 76 77 @Mock 78 private LocalBluetoothManager mLocalBluetoothManager; 79 @Mock 80 private LocalBluetoothProfileManager mLocalBluetoothProfileManager; 81 @Mock 82 private CachedBluetoothDeviceManager mCachedDeviceManager; 83 @Mock 84 private AudioProductStrategy mAudioProductStrategyMedia; 85 @Mock 86 private CachedBluetoothDevice mCachedBluetoothDevice; 87 @Mock 88 private BluetoothDevice mBluetoothDevice; 89 @Spy 90 private HearingAidAudioRoutingHelper mAudioRoutingHelper = 91 new HearingAidAudioRoutingHelper(mContext); 92 @Mock 93 private HearingAidHelper mHearingAidHelper; 94 private TestHearingDeviceAudioRoutingBasePreferenceController mController; 95 96 @Before setUp()97 public void setUp() { 98 final AudioDeviceAttributes hearingDeviceAttribute = new AudioDeviceAttributes( 99 AudioDeviceAttributes.ROLE_OUTPUT, 100 AudioDeviceInfo.TYPE_HEARING_AID, 101 TEST_DEVICE_ADDRESS); 102 103 ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager; 104 mLocalBluetoothManager = Utils.getLocalBtManager(mContext); 105 when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager); 106 when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager); 107 when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); 108 when(mBluetoothDevice.getAnonymizedAddress()).thenReturn(TEST_DEVICE_ADDRESS); 109 when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS); 110 doReturn(hearingDeviceAttribute).when( 111 mAudioRoutingHelper).getMatchedHearingDeviceAttributes(any()); 112 when(mAudioProductStrategyMedia.getAudioAttributesForLegacyStreamType( 113 AudioManager.STREAM_MUSIC)).thenReturn((new AudioAttributes.Builder()).build()); 114 when(mAudioRoutingHelper.getAudioProductStrategies()).thenReturn( 115 List.of(mAudioProductStrategyMedia)); 116 117 mController = new TestHearingDeviceAudioRoutingBasePreferenceController(mContext, 118 "test_key", 119 mAudioRoutingHelper, mHearingAidHelper); 120 mListPreference.setEntries(R.array.bluetooth_audio_routing_titles); 121 mListPreference.setEntryValues(R.array.bluetooth_audio_routing_values); 122 mListPreference.setSummary("%s"); 123 } 124 125 @Test updateState_routingValueAuto_expectedSummary()126 public void updateState_routingValueAuto_expectedSummary() { 127 mController.saveRoutingValue(mContext, HearingAidAudioRoutingConstants.RoutingValue.AUTO); 128 129 mController.updateState(mListPreference); 130 131 assertThat(mListPreference.getSummary().toString()).isEqualTo( 132 mListPreference.getEntries()[0].toString()); 133 } 134 135 @Test onPreferenceChange_routingValueHearingDevice_restoreSameValue()136 public void onPreferenceChange_routingValueHearingDevice_restoreSameValue() { 137 mController.onPreferenceChange(mListPreference, String.valueOf( 138 HearingAidAudioRoutingConstants.RoutingValue.HEARING_DEVICE)); 139 140 assertThat(mController.restoreRoutingValue(mContext)).isEqualTo( 141 HearingAidAudioRoutingConstants.RoutingValue.HEARING_DEVICE); 142 } 143 144 @Test onPreferenceChange_noMatchedDeviceAttributes_notCallSetStrategies()145 public void onPreferenceChange_noMatchedDeviceAttributes_notCallSetStrategies() { 146 when(mAudioRoutingHelper.getMatchedHearingDeviceAttributes(any())).thenReturn(null); 147 148 verify(mAudioRoutingHelper, never()).setPreferredDeviceRoutingStrategies(any(), isNull(), 149 anyInt()); 150 } 151 152 private static class TestHearingDeviceAudioRoutingBasePreferenceController extends 153 HearingDeviceAudioRoutingBasePreferenceController { 154 155 private static int sSavedRoutingValue; 156 TestHearingDeviceAudioRoutingBasePreferenceController(Context context, String preferenceKey, HearingAidAudioRoutingHelper audioRoutingHelper, HearingAidHelper hearingAidHelper)157 TestHearingDeviceAudioRoutingBasePreferenceController(Context context, 158 String preferenceKey, HearingAidAudioRoutingHelper audioRoutingHelper, 159 HearingAidHelper hearingAidHelper) { 160 super(context, preferenceKey, audioRoutingHelper, hearingAidHelper); 161 } 162 163 @Override getSupportedAttributeList()164 protected int[] getSupportedAttributeList() { 165 return new int[]{AudioAttributes.USAGE_MEDIA}; 166 } 167 168 @Override saveRoutingValue(Context context, int routingValue)169 protected void saveRoutingValue(Context context, int routingValue) { 170 sSavedRoutingValue = routingValue; 171 } 172 173 @Override restoreRoutingValue(Context context)174 protected int restoreRoutingValue(Context context) { 175 return sSavedRoutingValue; 176 } 177 } 178 } 179