Move 'Audio Output' to Accessibility hearing device page
* Extract the common part into HearingAidHelper. * Remove abstract getHearingDevice(). Change to get the hearing device when needed. * Move several classes from Bluetooth into Accessibility Bug: 281783079 Test: make RunSettingsRoboTests ROBOTEST_FILTER="(HearingDeviceAudioRoutingBasePreferenceControllerTest|AccessibilityHearingAidPreferenceControllerTest|HearingAidHelperTest|HearingAidAudioRoutingPreferenceControllerTest|HearingDeviceCallRoutingPreferenceControllerTest)" Change-Id: I79049107409b7086c6dcc8d48a6323e171ed1535
This commit is contained in:
@@ -129,7 +129,9 @@
|
|||||||
<!-- Title for all hearing devices related controls section. [CHAR LIMIT=60] -->
|
<!-- Title for all hearing devices related controls section. [CHAR LIMIT=60] -->
|
||||||
<string name="bluetooth_device_controls_general">For all available hearing devices</string>
|
<string name="bluetooth_device_controls_general">For all available hearing devices</string>
|
||||||
<!-- Connected devices settings. Title of the preference to show the entrance of the hearing device controls related page. [CHAR LIMIT=65] -->
|
<!-- Connected devices settings. Title of the preference to show the entrance of the hearing device controls related page. [CHAR LIMIT=65] -->
|
||||||
<string name="bluetooth_device_controls_title">Shortcuts & hearing aid compatibility</string>
|
<string name="bluetooth_device_controls_title">Hearing device settings</string>
|
||||||
|
<!-- Connected devices settings. Title of the preference to show the entrance of the hearing device controls related page. [CHAR LIMIT=65] -->
|
||||||
|
<string name="bluetooth_device_controls_summary">Audio output, shortcut, hearing aid compatibility</string>
|
||||||
<!-- Title for this device specific controls section. [CHAR LIMIT=30] -->
|
<!-- Title for this device specific controls section. [CHAR LIMIT=30] -->
|
||||||
<string name="bluetooth_device_controls_specific">For this device</string>
|
<string name="bluetooth_device_controls_specific">For this device</string>
|
||||||
<!-- Connected devices settings. Title of the preference to show the entrance of the audio output page. It can change different types of audio are played on phone or other bluetooth devices. [CHAR LIMIT=35] -->
|
<!-- Connected devices settings. Title of the preference to show the entrance of the audio output page. It can change different types of audio are played on phone or other bluetooth devices. [CHAR LIMIT=35] -->
|
||||||
|
@@ -31,7 +31,7 @@
|
|||||||
android:key="audio_routing_ringtone"
|
android:key="audio_routing_ringtone"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/bluetooth_ringtone_title"
|
android:title="@string/bluetooth_ringtone_title"
|
||||||
settings:controller="com.android.settings.bluetooth.HearingDeviceRingtoneRoutingPreferenceController" />
|
settings:controller="com.android.settings.accessibility.HearingDeviceRingtoneRoutingPreferenceController" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:entries="@array/bluetooth_audio_routing_titles"
|
android:entries="@array/bluetooth_audio_routing_titles"
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
android:key="audio_routing_call"
|
android:key="audio_routing_call"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/bluetooth_call_title"
|
android:title="@string/bluetooth_call_title"
|
||||||
settings:controller="com.android.settings.bluetooth.HearingDeviceCallRoutingPreferenceController" />
|
settings:controller="com.android.settings.accessibility.HearingDeviceCallRoutingPreferenceController" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:entries="@array/bluetooth_audio_routing_titles"
|
android:entries="@array/bluetooth_audio_routing_titles"
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
android:key="audio_routing_media"
|
android:key="audio_routing_media"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/bluetooth_media_title"
|
android:title="@string/bluetooth_media_title"
|
||||||
settings:controller="com.android.settings.bluetooth.HearingDeviceMediaRoutingPreferenceController" />
|
settings:controller="com.android.settings.accessibility.HearingDeviceMediaRoutingPreferenceController" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:entries="@array/bluetooth_audio_routing_titles"
|
android:entries="@array/bluetooth_audio_routing_titles"
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
android:key="audio_routing_system_sounds"
|
android:key="audio_routing_system_sounds"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/bluetooth_system_sounds_title"
|
android:title="@string/bluetooth_system_sounds_title"
|
||||||
settings:controller="com.android.settings.bluetooth.HearingDeviceSystemSoundsRoutingPreferenceController" />
|
settings:controller="com.android.settings.accessibility.HearingDeviceSystemSoundsRoutingPreferenceController" />
|
||||||
|
|
||||||
<com.android.settings.accessibility.AccessibilityFooterPreference
|
<com.android.settings.accessibility.AccessibilityFooterPreference
|
||||||
android:key="hearing_device_footer"
|
android:key="hearing_device_footer"
|
@@ -45,8 +45,17 @@
|
|||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="hearing_options_category"
|
android:key="hearing_options_category"
|
||||||
android:title="@string/accessibility_screen_option">
|
android:title="@string/accessibility_screen_option">
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="audio_routing"
|
||||||
|
android:title="@string/bluetooth_audio_routing_title"
|
||||||
|
android:summary="@string/bluetooth_audio_routing_summary"
|
||||||
|
android:fragment="com.android.settings.accessibility.AccessibilityAudioRoutingFragment"
|
||||||
|
settings:controller="com.android.settings.accessibility.HearingAidAudioRoutingPreferenceController"/>
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="hearing_aid_compatibility"
|
android:key="hearing_aid_compatibility"
|
||||||
|
android:order="30"
|
||||||
android:title="@string/accessibility_hac_mode_title"
|
android:title="@string/accessibility_hac_mode_title"
|
||||||
android:summary="@string/accessibility_hac_mode_summary"
|
android:summary="@string/accessibility_hac_mode_summary"
|
||||||
settings:searchable="true"
|
settings:searchable="true"
|
||||||
|
@@ -69,12 +69,7 @@
|
|||||||
android:key="device_companion_apps"/>
|
android:key="device_companion_apps"/>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="device_controls_general"
|
android:key="device_controls_general" />
|
||||||
android:title="@string/bluetooth_device_controls_general"/>
|
|
||||||
|
|
||||||
<PreferenceCategory
|
|
||||||
android:key="device_controls_specific"
|
|
||||||
android:title="@string/bluetooth_device_controls_specific"/>
|
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="spatial_audio_group"/>
|
android:key="spatial_audio_group"/>
|
||||||
|
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
|
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||||
|
|
||||||
|
import android.app.settings.SettingsEnums;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
||||||
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
|
|
||||||
|
/** Settings fragment containing bluetooth audio routing. */
|
||||||
|
public class AccessibilityAudioRoutingFragment extends RestrictedDashboardFragment {
|
||||||
|
private static final String TAG = "AccessibilityAudioRoutingFragment";
|
||||||
|
|
||||||
|
public AccessibilityAudioRoutingFragment() {
|
||||||
|
super(DISALLOW_CONFIG_BLUETOOTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMetricsCategory() {
|
||||||
|
return SettingsEnums.HEARING_AID_AUDIO_ROUTING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getPreferenceScreenResId() {
|
||||||
|
return R.xml.accessibility_audio_routing_fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getLogTag() {
|
||||||
|
return TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||||
|
new BaseSearchIndexProvider(R.xml.accessibility_audio_routing_fragment);
|
||||||
|
}
|
@@ -17,7 +17,6 @@
|
|||||||
package com.android.settings.accessibility;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
|
||||||
import android.bluetooth.BluetoothHapClient;
|
import android.bluetooth.BluetoothHapClient;
|
||||||
import android.bluetooth.BluetoothHearingAid;
|
import android.bluetooth.BluetoothHearingAid;
|
||||||
import android.bluetooth.BluetoothLeAudio;
|
import android.bluetooth.BluetoothLeAudio;
|
||||||
@@ -41,20 +40,14 @@ import com.android.settings.core.BasePreferenceController;
|
|||||||
import com.android.settings.core.SubSettingLauncher;
|
import com.android.settings.core.SubSettingLauncher;
|
||||||
import com.android.settingslib.bluetooth.BluetoothCallback;
|
import com.android.settingslib.bluetooth.BluetoothCallback;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
|
||||||
import com.android.settingslib.bluetooth.HapClientProfile;
|
|
||||||
import com.android.settingslib.bluetooth.HearingAidInfo;
|
import com.android.settingslib.bluetooth.HearingAidInfo;
|
||||||
import com.android.settingslib.bluetooth.HearingAidProfile;
|
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller that shows and updates the bluetooth device name
|
* Controller that shows and updates the bluetooth device name
|
||||||
@@ -73,10 +66,8 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
|||||||
};
|
};
|
||||||
|
|
||||||
private final LocalBluetoothManager mLocalBluetoothManager;
|
private final LocalBluetoothManager mLocalBluetoothManager;
|
||||||
private final BluetoothAdapter mBluetoothAdapter;
|
|
||||||
private final LocalBluetoothProfileManager mProfileManager;
|
private final LocalBluetoothProfileManager mProfileManager;
|
||||||
private final CachedBluetoothDeviceManager mCachedDeviceManager;
|
private final HearingAidHelper mHelper;
|
||||||
|
|
||||||
private FragmentManager mFragmentManager;
|
private FragmentManager mFragmentManager;
|
||||||
|
|
||||||
public AccessibilityHearingAidPreferenceController(Context context, String preferenceKey) {
|
public AccessibilityHearingAidPreferenceController(Context context, String preferenceKey) {
|
||||||
@@ -84,8 +75,7 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
|||||||
mLocalBluetoothManager = com.android.settings.bluetooth.Utils.getLocalBluetoothManager(
|
mLocalBluetoothManager = com.android.settings.bluetooth.Utils.getLocalBluetoothManager(
|
||||||
context);
|
context);
|
||||||
mProfileManager = mLocalBluetoothManager.getProfileManager();
|
mProfileManager = mLocalBluetoothManager.getProfileManager();
|
||||||
mCachedDeviceManager = mLocalBluetoothManager.getCachedDeviceManager();
|
mHelper = new HearingAidHelper(context);
|
||||||
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -96,7 +86,7 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
return isHearingAidSupported() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
return mHelper.isHearingAidSupported() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -111,7 +101,7 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
|||||||
// Can't get connected hearing aids when hearing aids related profiles are not ready. The
|
// Can't get connected hearing aids when hearing aids related profiles are not ready. The
|
||||||
// profiles will be ready after the services are connected. Needs to add listener and
|
// profiles will be ready after the services are connected. Needs to add listener and
|
||||||
// updates the information when all hearing aids related services are connected.
|
// updates the information when all hearing aids related services are connected.
|
||||||
if (isAnyHearingAidRelatedProfilesNotReady()) {
|
if (!mHelper.isAllHearingAidRelatedProfilesReady()) {
|
||||||
mProfileManager.addServiceListener(this);
|
mProfileManager.addServiceListener(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +116,7 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
|||||||
@Override
|
@Override
|
||||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||||
if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
|
if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
|
||||||
final CachedBluetoothDevice device = getConnectedHearingAidDevice();
|
final CachedBluetoothDevice device = mHelper.getConnectedHearingAidDevice();
|
||||||
if (FeatureFlagUtils.isEnabled(mContext,
|
if (FeatureFlagUtils.isEnabled(mContext,
|
||||||
FeatureFlagUtils.SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE)) {
|
FeatureFlagUtils.SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE)) {
|
||||||
launchHearingAidPage();
|
launchHearingAidPage();
|
||||||
@@ -144,10 +134,7 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence getSummary() {
|
public CharSequence getSummary() {
|
||||||
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
|
final CachedBluetoothDevice device = mHelper.getConnectedHearingAidDevice();
|
||||||
return mContext.getText(R.string.accessibility_hearingaid_not_connected_summary);
|
|
||||||
}
|
|
||||||
final CachedBluetoothDevice device = getConnectedHearingAidDevice();
|
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
return mContext.getText(R.string.accessibility_hearingaid_not_connected_summary);
|
return mContext.getText(R.string.accessibility_hearingaid_not_connected_summary);
|
||||||
}
|
}
|
||||||
@@ -203,7 +190,7 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceConnected() {
|
public void onServiceConnected() {
|
||||||
if (!isAnyHearingAidRelatedProfilesNotReady()) {
|
if (mHelper.isAllHearingAidRelatedProfilesReady()) {
|
||||||
updateState(mHearingAidPreference);
|
updateState(mHearingAidPreference);
|
||||||
mProfileManager.removeServiceListener(this);
|
mProfileManager.removeServiceListener(this);
|
||||||
}
|
}
|
||||||
@@ -218,53 +205,8 @@ public class AccessibilityHearingAidPreferenceController extends BasePreferenceC
|
|||||||
mFragmentManager = fragmentManager;
|
mFragmentManager = fragmentManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
CachedBluetoothDevice getConnectedHearingAidDevice() {
|
|
||||||
final List<BluetoothDevice> deviceList = getConnectedHearingAidDeviceList();
|
|
||||||
return deviceList.isEmpty() ? null : mCachedDeviceManager.findDevice(deviceList.get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getConnectedHearingAidDeviceNum() {
|
private int getConnectedHearingAidDeviceNum() {
|
||||||
return getConnectedHearingAidDeviceList().size();
|
return mHelper.getConnectedHearingAidDeviceList().size();
|
||||||
}
|
|
||||||
|
|
||||||
private List<BluetoothDevice> getConnectedHearingAidDeviceList() {
|
|
||||||
if (!isHearingAidSupported()) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
final List<BluetoothDevice> deviceList = new ArrayList<>();
|
|
||||||
final HapClientProfile hapClientProfile = mProfileManager.getHapClientProfile();
|
|
||||||
if (hapClientProfile != null) {
|
|
||||||
deviceList.addAll(hapClientProfile.getConnectedDevices());
|
|
||||||
}
|
|
||||||
final HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile();
|
|
||||||
if (hearingAidProfile != null) {
|
|
||||||
deviceList.addAll(hearingAidProfile.getConnectedDevices());
|
|
||||||
}
|
|
||||||
return deviceList.stream()
|
|
||||||
.distinct()
|
|
||||||
.filter(d -> !mCachedDeviceManager.isSubDevice(d)).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isHearingAidSupported() {
|
|
||||||
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final List<Integer> supportedList = mBluetoothAdapter.getSupportedProfiles();
|
|
||||||
return supportedList.contains(BluetoothProfile.HEARING_AID)
|
|
||||||
|| supportedList.contains(BluetoothProfile.HAP_CLIENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isAnyHearingAidRelatedProfilesNotReady() {
|
|
||||||
HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile();
|
|
||||||
if (hearingAidProfile != null && !hearingAidProfile.isProfileReady()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
HapClientProfile hapClientProfile = mProfileManager.getHapClientProfile();
|
|
||||||
if (hapClientProfile != null && !hapClientProfile.isProfileReady()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
|
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
|
||||||
|
@@ -39,7 +39,7 @@ public class AccessibilityHearingAidsFragment extends AccessibilityShortcutPrefe
|
|||||||
|
|
||||||
private static final String TAG = "AccessibilityHearingAidsFragment";
|
private static final String TAG = "AccessibilityHearingAidsFragment";
|
||||||
private static final String KEY_HEARING_OPTIONS_CATEGORY = "hearing_options_category";
|
private static final String KEY_HEARING_OPTIONS_CATEGORY = "hearing_options_category";
|
||||||
private static final int FIRST_PREFERENCE_IN_CATEGORY_INDEX = -1;
|
private static final int SHORTCUT_PREFERENCE_IN_CATEGORY_INDEX = 20;
|
||||||
private String mFeatureName;
|
private String mFeatureName;
|
||||||
|
|
||||||
public AccessibilityHearingAidsFragment() {
|
public AccessibilityHearingAidsFragment() {
|
||||||
@@ -65,7 +65,7 @@ public class AccessibilityHearingAidsFragment extends AccessibilityShortcutPrefe
|
|||||||
final View view = super.onCreateView(inflater, container, savedInstanceState);
|
final View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
final PreferenceCategory controlCategory = findPreference(KEY_HEARING_OPTIONS_CATEGORY);
|
final PreferenceCategory controlCategory = findPreference(KEY_HEARING_OPTIONS_CATEGORY);
|
||||||
// To move the shortcut preference under controlCategory need to remove the original added.
|
// To move the shortcut preference under controlCategory need to remove the original added.
|
||||||
mShortcutPreference.setOrder(FIRST_PREFERENCE_IN_CATEGORY_INDEX);
|
mShortcutPreference.setOrder(SHORTCUT_PREFERENCE_IN_CATEGORY_INDEX);
|
||||||
getPreferenceScreen().removePreference(mShortcutPreference);
|
getPreferenceScreen().removePreference(mShortcutPreference);
|
||||||
controlCategory.addPreference(mShortcutPreference);
|
controlCategory.addPreference(mShortcutPreference);
|
||||||
return view;
|
return view;
|
||||||
|
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.FeatureFlagUtils;
|
||||||
|
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The controller of the audio routing.
|
||||||
|
*/
|
||||||
|
public class HearingAidAudioRoutingPreferenceController extends BasePreferenceController {
|
||||||
|
public HearingAidAudioRoutingPreferenceController(Context context,
|
||||||
|
String preferenceKey) {
|
||||||
|
super(context, preferenceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_AUDIO_ROUTING)
|
||||||
|
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||||
|
}
|
||||||
|
}
|
114
src/com/android/settings/accessibility/HearingAidHelper.java
Normal file
114
src/com/android/settings/accessibility/HearingAidHelper.java
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||||
|
import com.android.settingslib.bluetooth.HapClientProfile;
|
||||||
|
import com.android.settingslib.bluetooth.HearingAidProfile;
|
||||||
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
|
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class to get and check hearing aids and its status.
|
||||||
|
*/
|
||||||
|
public class HearingAidHelper {
|
||||||
|
|
||||||
|
private final BluetoothAdapter mBluetoothAdapter;
|
||||||
|
private final LocalBluetoothProfileManager mProfileManager;
|
||||||
|
private final CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||||
|
|
||||||
|
public HearingAidHelper(Context context) {
|
||||||
|
final LocalBluetoothManager localBluetoothManager =
|
||||||
|
com.android.settings.bluetooth.Utils.getLocalBluetoothManager(context);
|
||||||
|
mProfileManager = localBluetoothManager.getProfileManager();
|
||||||
|
mCachedDeviceManager = localBluetoothManager.getCachedDeviceManager();
|
||||||
|
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the connected hearing aids device whose profiles are
|
||||||
|
* {@link BluetoothProfile#HEARING_AID} or {@link BluetoothProfile#HAP_CLIENT}.
|
||||||
|
*
|
||||||
|
* @return a list of hearing aids {@link BluetoothDevice} objects
|
||||||
|
*/
|
||||||
|
public List<BluetoothDevice> getConnectedHearingAidDeviceList() {
|
||||||
|
if (!isHearingAidSupported()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
final List<BluetoothDevice> deviceList = new ArrayList<>();
|
||||||
|
final HapClientProfile hapClientProfile = mProfileManager.getHapClientProfile();
|
||||||
|
if (hapClientProfile != null) {
|
||||||
|
deviceList.addAll(hapClientProfile.getConnectedDevices());
|
||||||
|
}
|
||||||
|
final HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile();
|
||||||
|
if (hearingAidProfile != null) {
|
||||||
|
deviceList.addAll(hearingAidProfile.getConnectedDevices());
|
||||||
|
}
|
||||||
|
return deviceList.stream()
|
||||||
|
.distinct()
|
||||||
|
.filter(d -> !mCachedDeviceManager.isSubDevice(d)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the first connected hearing aids device.
|
||||||
|
*
|
||||||
|
* @return a {@link CachedBluetoothDevice} that is hearing aids device
|
||||||
|
*/
|
||||||
|
public CachedBluetoothDevice getConnectedHearingAidDevice() {
|
||||||
|
final List<BluetoothDevice> deviceList = getConnectedHearingAidDeviceList();
|
||||||
|
return deviceList.isEmpty() ? null : mCachedDeviceManager.findDevice(deviceList.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if {@link BluetoothProfile#HEARING_AID} or {@link BluetoothProfile#HAP_CLIENT}
|
||||||
|
* supported.
|
||||||
|
*/
|
||||||
|
public boolean isHearingAidSupported() {
|
||||||
|
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final List<Integer> supportedList = mBluetoothAdapter.getSupportedProfiles();
|
||||||
|
return supportedList.contains(BluetoothProfile.HEARING_AID)
|
||||||
|
|| supportedList.contains(BluetoothProfile.HAP_CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if {@link BluetoothProfile#HEARING_AID} or {@link BluetoothProfile#HAP_CLIENT}
|
||||||
|
* profiles all ready.
|
||||||
|
*/
|
||||||
|
public boolean isAllHearingAidRelatedProfilesReady() {
|
||||||
|
HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile();
|
||||||
|
if (hearingAidProfile != null && !hearingAidProfile.isProfileReady()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
HapClientProfile hapClientProfile = mProfileManager.getHapClientProfile();
|
||||||
|
if (hapClientProfile != null && !hapClientProfile.isProfileReady()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -47,19 +47,24 @@ public abstract class HearingDeviceAudioRoutingBasePreferenceController extends
|
|||||||
private static final String TAG = "HARoutingBasePreferenceController";
|
private static final String TAG = "HARoutingBasePreferenceController";
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private final HearingAidAudioRoutingHelper mHelper;
|
private final HearingAidAudioRoutingHelper mAudioRoutingHelper;
|
||||||
|
private final HearingAidHelper mHearingAidHelper;
|
||||||
|
|
||||||
public HearingDeviceAudioRoutingBasePreferenceController(Context context,
|
public HearingDeviceAudioRoutingBasePreferenceController(Context context,
|
||||||
String preferenceKey) {
|
String preferenceKey) {
|
||||||
super(context, preferenceKey);
|
this(context, preferenceKey,
|
||||||
mHelper = new HearingAidAudioRoutingHelper(context);
|
new HearingAidAudioRoutingHelper(context),
|
||||||
|
new HearingAidHelper(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public HearingDeviceAudioRoutingBasePreferenceController(Context context,
|
public HearingDeviceAudioRoutingBasePreferenceController(Context context,
|
||||||
String preferenceKey, HearingAidAudioRoutingHelper helper) {
|
String preferenceKey, HearingAidAudioRoutingHelper audioRoutingHelper,
|
||||||
|
HearingAidHelper hearingAidHelper) {
|
||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
mHelper = helper;
|
|
||||||
|
mAudioRoutingHelper = audioRoutingHelper;
|
||||||
|
mHearingAidHelper = hearingAidHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,7 +86,11 @@ public abstract class HearingDeviceAudioRoutingBasePreferenceController extends
|
|||||||
final Integer routingValue = Ints.tryParse((String) newValue);
|
final Integer routingValue = Ints.tryParse((String) newValue);
|
||||||
|
|
||||||
saveRoutingValue(mContext, routingValue);
|
saveRoutingValue(mContext, routingValue);
|
||||||
trySetAudioRoutingConfig(getSupportedAttributeList(), getHearingDevice(), routingValue);
|
final CachedBluetoothDevice device = mHearingAidHelper.getConnectedHearingAidDevice();
|
||||||
|
if (device != null) {
|
||||||
|
trySetAudioRoutingConfig(getSupportedAttributeList(),
|
||||||
|
mHearingAidHelper.getConnectedHearingAidDevice(), routingValue);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -89,10 +98,10 @@ public abstract class HearingDeviceAudioRoutingBasePreferenceController extends
|
|||||||
private void trySetAudioRoutingConfig(int[] audioAttributes,
|
private void trySetAudioRoutingConfig(int[] audioAttributes,
|
||||||
CachedBluetoothDevice hearingDevice,
|
CachedBluetoothDevice hearingDevice,
|
||||||
@HearingAidAudioRoutingConstants.RoutingValue int routingValue) {
|
@HearingAidAudioRoutingConstants.RoutingValue int routingValue) {
|
||||||
final List<AudioProductStrategy> supportedStrategies = mHelper.getSupportedStrategies(
|
final List<AudioProductStrategy> supportedStrategies =
|
||||||
audioAttributes);
|
mAudioRoutingHelper.getSupportedStrategies(audioAttributes);
|
||||||
final AudioDeviceAttributes hearingDeviceAttributes =
|
final AudioDeviceAttributes hearingDeviceAttributes =
|
||||||
mHelper.getMatchedHearingDeviceAttributes(hearingDevice);
|
mAudioRoutingHelper.getMatchedHearingDeviceAttributes(hearingDevice);
|
||||||
if (hearingDeviceAttributes == null) {
|
if (hearingDeviceAttributes == null) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG,
|
Log.d(TAG,
|
||||||
@@ -103,8 +112,8 @@ public abstract class HearingDeviceAudioRoutingBasePreferenceController extends
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean status = mHelper.setPreferredDeviceRoutingStrategies(supportedStrategies,
|
final boolean status = mAudioRoutingHelper.setPreferredDeviceRoutingStrategies(
|
||||||
hearingDeviceAttributes, routingValue);
|
supportedStrategies, hearingDeviceAttributes, routingValue);
|
||||||
|
|
||||||
if (!status) {
|
if (!status) {
|
||||||
final List<String> strategiesName = supportedStrategies.stream()
|
final List<String> strategiesName = supportedStrategies.stream()
|
||||||
@@ -121,12 +130,6 @@ public abstract class HearingDeviceAudioRoutingBasePreferenceController extends
|
|||||||
*/
|
*/
|
||||||
protected abstract int[] getSupportedAttributeList();
|
protected abstract int[] getSupportedAttributeList();
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the {@link CachedBluetoothDevice} hearing device that is used to configure audio
|
|
||||||
* routing.
|
|
||||||
*/
|
|
||||||
protected abstract CachedBluetoothDevice getHearingDevice();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the routing value.
|
* Saves the routing value.
|
||||||
*
|
*
|
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -35,15 +35,6 @@ public class HearingDeviceCallRoutingPreferenceController extends
|
|||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes objects in this controller. Need to call this before using the controller.
|
|
||||||
*
|
|
||||||
* @param cachedBluetoothDevice the hearing device to configure audio routing
|
|
||||||
*/
|
|
||||||
public void init(CachedBluetoothDevice cachedBluetoothDevice) {
|
|
||||||
mHearingDevice = cachedBluetoothDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
return Utils.isVoiceCapable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
return Utils.isVoiceCapable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||||
@@ -54,11 +45,6 @@ public class HearingDeviceCallRoutingPreferenceController extends
|
|||||||
return HearingAidAudioRoutingConstants.CALL_ROUTING_ATTRIBUTES;
|
return HearingAidAudioRoutingConstants.CALL_ROUTING_ATTRIBUTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CachedBluetoothDevice getHearingDevice() {
|
|
||||||
return mHearingDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void saveRoutingValue(Context context, int routingValue) {
|
protected void saveRoutingValue(Context context, int routingValue) {
|
||||||
Settings.Secure.putInt(context.getContentResolver(),
|
Settings.Secure.putInt(context.getContentResolver(),
|
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -34,26 +34,12 @@ public class HearingDeviceMediaRoutingPreferenceController extends
|
|||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes objects in this controller. Need to call this before using the controller.
|
|
||||||
*
|
|
||||||
* @param cachedBluetoothDevice the hearing device to configure audio routing
|
|
||||||
*/
|
|
||||||
public void init(CachedBluetoothDevice cachedBluetoothDevice) {
|
|
||||||
mHearingDevice = cachedBluetoothDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int[] getSupportedAttributeList() {
|
protected int[] getSupportedAttributeList() {
|
||||||
return HearingAidAudioRoutingConstants.MEDIA_ROUTING_ATTRIBUTES;
|
return HearingAidAudioRoutingConstants.MEDIA_ROUTING_ATTRIBUTES;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CachedBluetoothDevice getHearingDevice() {
|
|
||||||
return mHearingDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void saveRoutingValue(Context context, int routingValue) {
|
protected void saveRoutingValue(Context context, int routingValue) {
|
||||||
Settings.Secure.putInt(context.getContentResolver(),
|
Settings.Secure.putInt(context.getContentResolver(),
|
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -34,26 +34,12 @@ public class HearingDeviceRingtoneRoutingPreferenceController extends
|
|||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes objects in this controller. Need to call this before using the controller.
|
|
||||||
*
|
|
||||||
* @param cachedBluetoothDevice the hearing device to configure audio routing
|
|
||||||
*/
|
|
||||||
public void init(CachedBluetoothDevice cachedBluetoothDevice) {
|
|
||||||
mHearingDevice = cachedBluetoothDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int[] getSupportedAttributeList() {
|
protected int[] getSupportedAttributeList() {
|
||||||
return HearingAidAudioRoutingConstants.RINGTONE_ROUTING_ATTRIBUTE;
|
return HearingAidAudioRoutingConstants.RINGTONE_ROUTING_ATTRIBUTE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CachedBluetoothDevice getHearingDevice() {
|
|
||||||
return mHearingDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void saveRoutingValue(Context context, int routingValue) {
|
protected void saveRoutingValue(Context context, int routingValue) {
|
||||||
Settings.Secure.putInt(context.getContentResolver(),
|
Settings.Secure.putInt(context.getContentResolver(),
|
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -35,26 +35,12 @@ public class HearingDeviceSystemSoundsRoutingPreferenceController extends
|
|||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes objects in this controller. Need to call this before using the controller.
|
|
||||||
*
|
|
||||||
* @param cachedBluetoothDevice the hearing device to configure audio routing
|
|
||||||
*/
|
|
||||||
public void init(CachedBluetoothDevice cachedBluetoothDevice) {
|
|
||||||
mHearingDevice = cachedBluetoothDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int[] getSupportedAttributeList() {
|
protected int[] getSupportedAttributeList() {
|
||||||
return HearingAidAudioRoutingConstants.SYSTEM_SOUNDS_ROUTING_ATTRIBUTES;
|
return HearingAidAudioRoutingConstants.SYSTEM_SOUNDS_ROUTING_ATTRIBUTES;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CachedBluetoothDevice getHearingDevice() {
|
|
||||||
return mHearingDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void saveRoutingValue(Context context, int routingValue) {
|
protected void saveRoutingValue(Context context, int routingValue) {
|
||||||
Settings.Secure.putInt(context.getContentResolver(),
|
Settings.Secure.putInt(context.getContentResolver(),
|
@@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2022 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
|
||||||
|
|
||||||
import static com.android.settings.bluetooth.BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.FeatureFlagUtils;
|
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceCategory;
|
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
|
||||||
import androidx.preference.PreferenceScreen;
|
|
||||||
|
|
||||||
import com.android.settings.R;
|
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
|
||||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The controller of the audio routing in the bluetooth detail settings.
|
|
||||||
*/
|
|
||||||
public class BluetoothDetailsAudioRoutingController extends BluetoothDetailsController {
|
|
||||||
|
|
||||||
private static final String KEY_DEVICE_CONTROLS_SPECIFIC_GROUP = "device_controls_specific";
|
|
||||||
@VisibleForTesting
|
|
||||||
static final String KEY_AUDIO_ROUTING = "audio_routing";
|
|
||||||
|
|
||||||
public BluetoothDetailsAudioRoutingController(Context context,
|
|
||||||
PreferenceFragmentCompat fragment, CachedBluetoothDevice device, Lifecycle lifecycle) {
|
|
||||||
super(context, fragment, device, lifecycle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAvailable() {
|
|
||||||
return mCachedDevice.isHearingAidDevice() && FeatureFlagUtils.isEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_AUDIO_ROUTING);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void init(PreferenceScreen screen) {
|
|
||||||
if (!mCachedDevice.isHearingAidDevice()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final PreferenceCategory prefCategory = screen.findPreference(getPreferenceKey());
|
|
||||||
final Preference pref = createAudioRoutingPreference(prefCategory.getContext());
|
|
||||||
prefCategory.addPreference(pref);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void refresh() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPreferenceKey() {
|
|
||||||
return KEY_DEVICE_CONTROLS_SPECIFIC_GROUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Preference createAudioRoutingPreference(Context context) {
|
|
||||||
final Preference preference = new Preference(context);
|
|
||||||
|
|
||||||
preference.setKey(KEY_AUDIO_ROUTING);
|
|
||||||
preference.setTitle(context.getString(R.string.bluetooth_audio_routing_title));
|
|
||||||
preference.setSummary(context.getString(R.string.bluetooth_audio_routing_summary));
|
|
||||||
final Bundle extras = preference.getExtras();
|
|
||||||
extras.putString(KEY_DEVICE_ADDRESS, mCachedDevice.getAddress());
|
|
||||||
preference.setFragment(BluetoothDetailsAudioRoutingFragment.class.getName());
|
|
||||||
|
|
||||||
return preference;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2023 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
|
||||||
|
|
||||||
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
|
||||||
|
|
||||||
import static com.android.settings.bluetooth.BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS;
|
|
||||||
|
|
||||||
import android.app.settings.SettingsEnums;
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
|
||||||
|
|
||||||
import com.android.settings.R;
|
|
||||||
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
|
||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
|
||||||
|
|
||||||
/** Settings fragment containing bluetooth audio routing. */
|
|
||||||
public class BluetoothDetailsAudioRoutingFragment extends RestrictedDashboardFragment {
|
|
||||||
|
|
||||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
|
||||||
new BaseSearchIndexProvider(R.xml.bluetooth_audio_routing_fragment);
|
|
||||||
private static final String TAG = "BluetoothDetailsAudioRoutingFragment";
|
|
||||||
@VisibleForTesting
|
|
||||||
CachedBluetoothDevice mCachedDevice;
|
|
||||||
|
|
||||||
public BluetoothDetailsAudioRoutingFragment() {
|
|
||||||
super(DISALLOW_CONFIG_BLUETOOTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttach(Context context) {
|
|
||||||
super.onAttach(context);
|
|
||||||
final LocalBluetoothManager localBtMgr = Utils.getLocalBtManager(context);
|
|
||||||
final CachedBluetoothDeviceManager cachedDeviceMgr = localBtMgr.getCachedDeviceManager();
|
|
||||||
final BluetoothDevice bluetoothDevice = localBtMgr.getBluetoothAdapter().getRemoteDevice(
|
|
||||||
getArguments().getString(KEY_DEVICE_ADDRESS));
|
|
||||||
|
|
||||||
mCachedDevice = cachedDeviceMgr.findDevice(bluetoothDevice);
|
|
||||||
if (mCachedDevice == null) {
|
|
||||||
// Close this page if device is null with invalid device mac address
|
|
||||||
Log.w(TAG, "onAttach() CachedDevice is null! Can not find address: "
|
|
||||||
+ bluetoothDevice.getAnonymizedAddress());
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
use(HearingDeviceRingtoneRoutingPreferenceController.class).init(mCachedDevice);
|
|
||||||
use(HearingDeviceCallRoutingPreferenceController.class).init(mCachedDevice);
|
|
||||||
use(HearingDeviceMediaRoutingPreferenceController.class).init(mCachedDevice);
|
|
||||||
use(HearingDeviceSystemSoundsRoutingPreferenceController.class).init(mCachedDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMetricsCategory() {
|
|
||||||
return SettingsEnums.BLUETOOTH_AUDIO_ROUTING;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getPreferenceScreenResId() {
|
|
||||||
return R.xml.bluetooth_audio_routing_fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getLogTag() {
|
|
||||||
return TAG;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -34,7 +34,7 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
|
|||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The controller of the hearing device controls in the bluetooth detail settings.
|
* The controller of the hearing device settings to launch Hearing device page.
|
||||||
*/
|
*/
|
||||||
public class BluetoothDetailsHearingDeviceControlsController extends BluetoothDetailsController
|
public class BluetoothDetailsHearingDeviceControlsController extends BluetoothDetailsController
|
||||||
implements Preference.OnPreferenceClickListener {
|
implements Preference.OnPreferenceClickListener {
|
||||||
@@ -87,6 +87,7 @@ public class BluetoothDetailsHearingDeviceControlsController extends BluetoothDe
|
|||||||
final Preference preference = new Preference(context);
|
final Preference preference = new Preference(context);
|
||||||
preference.setKey(KEY_HEARING_DEVICE_CONTROLS);
|
preference.setKey(KEY_HEARING_DEVICE_CONTROLS);
|
||||||
preference.setTitle(context.getString(R.string.bluetooth_device_controls_title));
|
preference.setTitle(context.getString(R.string.bluetooth_device_controls_title));
|
||||||
|
preference.setSummary(context.getString(R.string.bluetooth_device_controls_summary));
|
||||||
preference.setOnPreferenceClickListener(this);
|
preference.setOnPreferenceClickListener(this);
|
||||||
|
|
||||||
return preference;
|
return preference;
|
||||||
|
@@ -314,8 +314,6 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
|||||||
lifecycle));
|
lifecycle));
|
||||||
controllers.add(new BluetoothDetailsHearingDeviceControlsController(context, this,
|
controllers.add(new BluetoothDetailsHearingDeviceControlsController(context, this,
|
||||||
mCachedDevice, lifecycle));
|
mCachedDevice, lifecycle));
|
||||||
controllers.add(new BluetoothDetailsAudioRoutingController(context, this, mCachedDevice,
|
|
||||||
lifecycle));
|
|
||||||
}
|
}
|
||||||
return controllers;
|
return controllers;
|
||||||
}
|
}
|
||||||
|
@@ -24,25 +24,22 @@ import static org.mockito.Mockito.spy;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.bluetooth.BluetoothHapClient;
|
import android.bluetooth.BluetoothHapClient;
|
||||||
import android.bluetooth.BluetoothHearingAid;
|
import android.bluetooth.BluetoothHearingAid;
|
||||||
import android.bluetooth.BluetoothProfile;
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.bluetooth.Utils;
|
import com.android.settings.bluetooth.Utils;
|
||||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
|
||||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||||
import com.android.settings.utils.ActivityControllerWrapper;
|
|
||||||
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
import com.android.settingslib.bluetooth.BluetoothEventManager;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||||
@@ -55,11 +52,12 @@ import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
|||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.robolectric.Robolectric;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
import org.robolectric.shadow.api.Shadow;
|
import org.robolectric.shadow.api.Shadow;
|
||||||
@@ -74,6 +72,9 @@ import java.util.Set;
|
|||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class})
|
@Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class})
|
||||||
public class AccessibilityHearingAidPreferenceControllerTest {
|
public class AccessibilityHearingAidPreferenceControllerTest {
|
||||||
|
@Rule
|
||||||
|
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||||
|
|
||||||
private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
|
private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
|
||||||
private static final String TEST_DEVICE_ADDRESS_2 = "00:A2:A2:A2:A2:A2";
|
private static final String TEST_DEVICE_ADDRESS_2 = "00:A2:A2:A2:A2:A2";
|
||||||
private static final String TEST_DEVICE_NAME = "TEST_HEARING_AID_BT_DEVICE_NAME";
|
private static final String TEST_DEVICE_NAME = "TEST_HEARING_AID_BT_DEVICE_NAME";
|
||||||
@@ -82,7 +83,8 @@ public class AccessibilityHearingAidPreferenceControllerTest {
|
|||||||
private BluetoothAdapter mBluetoothAdapter;
|
private BluetoothAdapter mBluetoothAdapter;
|
||||||
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||||
private BluetoothDevice mBluetoothDevice;
|
private BluetoothDevice mBluetoothDevice;
|
||||||
private Activity mContext;
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
|
|
||||||
private Preference mHearingAidPreference;
|
private Preference mHearingAidPreference;
|
||||||
private AccessibilityHearingAidPreferenceController mPreferenceController;
|
private AccessibilityHearingAidPreferenceController mPreferenceController;
|
||||||
private ShadowApplication mShadowApplication;
|
private ShadowApplication mShadowApplication;
|
||||||
@@ -106,11 +108,7 @@ public class AccessibilityHearingAidPreferenceControllerTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
|
||||||
mShadowApplication = ShadowApplication.getInstance();
|
mShadowApplication = ShadowApplication.getInstance();
|
||||||
|
|
||||||
mContext = spy((Activity) ActivityControllerWrapper.setup(
|
|
||||||
Robolectric.buildActivity(Activity.class)).get());
|
|
||||||
setupEnvironment();
|
setupEnvironment();
|
||||||
|
|
||||||
mHearingAidPreference = new Preference(mContext);
|
mHearingAidPreference = new Preference(mContext);
|
||||||
@@ -274,65 +272,6 @@ public class AccessibilityHearingAidPreferenceControllerTest {
|
|||||||
verify(mPreferenceController).launchBluetoothDeviceDetailSetting(mCachedBluetoothDevice);
|
verify(mPreferenceController).launchBluetoothDeviceDetailSetting(mCachedBluetoothDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onSupportHearingAidProfile_isAvailable() {
|
|
||||||
mShadowBluetoothAdapter.clearSupportedProfiles();
|
|
||||||
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HEARING_AID);
|
|
||||||
mPreferenceController = new AccessibilityHearingAidPreferenceController(mContext,
|
|
||||||
HEARING_AID_PREFERENCE);
|
|
||||||
mPreferenceController.setPreference(mHearingAidPreference);
|
|
||||||
|
|
||||||
assertThat(mPreferenceController.isAvailable()).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onSupportHapClientProfile_isAvailable() {
|
|
||||||
mShadowBluetoothAdapter.clearSupportedProfiles();
|
|
||||||
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HAP_CLIENT);
|
|
||||||
mPreferenceController = new AccessibilityHearingAidPreferenceController(mContext,
|
|
||||||
HEARING_AID_PREFERENCE);
|
|
||||||
mPreferenceController.setPreference(mHearingAidPreference);
|
|
||||||
|
|
||||||
assertThat(mPreferenceController.isAvailable()).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onNotSupportAnyHearingAidRelatedProfile_isNotAvailable() {
|
|
||||||
mShadowBluetoothAdapter.clearSupportedProfiles();
|
|
||||||
mPreferenceController = new AccessibilityHearingAidPreferenceController(mContext,
|
|
||||||
HEARING_AID_PREFERENCE);
|
|
||||||
mPreferenceController.setPreference(mHearingAidPreference);
|
|
||||||
|
|
||||||
assertThat(mPreferenceController.isAvailable()).isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getConnectedHearingAidDevice_doNotReturnSubDevice() {
|
|
||||||
when(mHearingAidProfile.getConnectedDevices()).thenReturn(generateHearingAidDeviceList());
|
|
||||||
when(mLocalBluetoothManager.getCachedDeviceManager().isSubDevice(mBluetoothDevice))
|
|
||||||
.thenReturn(true);
|
|
||||||
|
|
||||||
assertThat(mPreferenceController.getConnectedHearingAidDevice()).isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Config(shadows = ShadowAlertDialogCompat.class)
|
|
||||||
public void onActiveDeviceChanged_hearingAidProfile_launchHearingAidPairingDialog() {
|
|
||||||
final FragmentActivity mActivity = Robolectric.setupActivity(FragmentActivity.class);
|
|
||||||
when(mCachedBluetoothDevice.isConnectedAshaHearingAidDevice()).thenReturn(true);
|
|
||||||
when(mCachedBluetoothDevice.getDeviceMode()).thenReturn(
|
|
||||||
HearingAidInfo.DeviceMode.MODE_BINAURAL);
|
|
||||||
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
|
|
||||||
HearingAidInfo.DeviceSide.SIDE_LEFT);
|
|
||||||
mPreferenceController.setFragmentManager(mActivity.getSupportFragmentManager());
|
|
||||||
|
|
||||||
mPreferenceController.onActiveDeviceChanged(mCachedBluetoothDevice,
|
|
||||||
BluetoothProfile.HEARING_AID);
|
|
||||||
|
|
||||||
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
|
|
||||||
assertThat(dialog.isShowing()).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onServiceConnected_onHearingAidProfileConnected_updateSummary() {
|
public void onServiceConnected_onHearingAidProfileConnected_updateSummary() {
|
||||||
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
|
when(mCachedBluetoothDevice.getDeviceSide()).thenReturn(
|
||||||
|
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
|
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||||
|
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.FeatureFlagUtils;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.junit.MockitoJUnit;
|
||||||
|
import org.mockito.junit.MockitoRule;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
|
||||||
|
/** Tests for {@link HearingAidAudioRoutingPreferenceController}. */
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
public class HearingAidAudioRoutingPreferenceControllerTest {
|
||||||
|
@Rule
|
||||||
|
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||||
|
|
||||||
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
|
|
||||||
|
private HearingAidAudioRoutingPreferenceController mController;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mController = new HearingAidAudioRoutingPreferenceController(mContext, "test_key");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAvailabilityStatus_audioRoutingNotSupported_returnUnsupported() {
|
||||||
|
FeatureFlagUtils.setEnabled(mContext,
|
||||||
|
FeatureFlagUtils.SETTINGS_AUDIO_ROUTING, false);
|
||||||
|
|
||||||
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getAvailabilityStatus_audioRoutingNotSupported_available() {
|
||||||
|
FeatureFlagUtils.setEnabled(mContext,
|
||||||
|
FeatureFlagUtils.SETTINGS_AUDIO_ROUTING, true);
|
||||||
|
|
||||||
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import com.android.settings.bluetooth.Utils;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||||
|
import com.android.settingslib.bluetooth.HapClientProfile;
|
||||||
|
import com.android.settingslib.bluetooth.HearingAidProfile;
|
||||||
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
|
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnit;
|
||||||
|
import org.mockito.junit.MockitoRule;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadow.api.Shadow;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
/** Tests for {@link HearingAidHelper}. */
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class})
|
||||||
|
public class HearingAidHelperTest {
|
||||||
|
@Rule
|
||||||
|
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||||
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
|
private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private LocalBluetoothManager mLocalBluetoothManager;
|
||||||
|
@Mock
|
||||||
|
private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
|
||||||
|
@Mock
|
||||||
|
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||||
|
@Mock
|
||||||
|
private CachedBluetoothDevice mCachedBluetoothDevice;
|
||||||
|
@Mock
|
||||||
|
private HearingAidProfile mHearingAidProfile;
|
||||||
|
@Mock
|
||||||
|
private HapClientProfile mHapClientProfile;
|
||||||
|
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
|
||||||
|
private BluetoothAdapter mBluetoothAdapter;
|
||||||
|
private BluetoothDevice mBluetoothDevice;
|
||||||
|
private HearingAidHelper mHelper;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
|
||||||
|
mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
|
||||||
|
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
mShadowBluetoothAdapter = Shadow.extract(mBluetoothAdapter);
|
||||||
|
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS);
|
||||||
|
when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
|
||||||
|
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
|
||||||
|
when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice);
|
||||||
|
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
|
||||||
|
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
|
||||||
|
when(mLocalBluetoothProfileManager.getHapClientProfile()).thenReturn(mHapClientProfile);
|
||||||
|
|
||||||
|
mHelper = new HearingAidHelper(mContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isHearingAidSupported_supported_returnTrue() {
|
||||||
|
mBluetoothAdapter.enable();
|
||||||
|
mShadowBluetoothAdapter.clearSupportedProfiles();
|
||||||
|
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HEARING_AID);
|
||||||
|
|
||||||
|
assertThat(mHelper.isHearingAidSupported()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isHearingAidSupported_bluetoothOff_returnFalse() {
|
||||||
|
mShadowBluetoothAdapter.clearSupportedProfiles();
|
||||||
|
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HEARING_AID);
|
||||||
|
mBluetoothAdapter.disable();
|
||||||
|
|
||||||
|
assertThat(mHelper.isHearingAidSupported()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isAllHearingAidRelatedProfilesReady_allReady_returnTrue() {
|
||||||
|
when(mHearingAidProfile.isProfileReady()).thenReturn(true);
|
||||||
|
when(mHapClientProfile.isProfileReady()).thenReturn(true);
|
||||||
|
|
||||||
|
assertThat(mHelper.isAllHearingAidRelatedProfilesReady()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isAllHearingAidRelatedProfilesReady_notFullReady_returnFalse() {
|
||||||
|
when(mHearingAidProfile.isProfileReady()).thenReturn(false);
|
||||||
|
when(mHapClientProfile.isProfileReady()).thenReturn(true);
|
||||||
|
|
||||||
|
assertThat(mHelper.isAllHearingAidRelatedProfilesReady()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getConnectedHearingAidDeviceList_oneDeviceAdded_getOneDevice() {
|
||||||
|
mBluetoothAdapter.enable();
|
||||||
|
mShadowBluetoothAdapter.clearSupportedProfiles();
|
||||||
|
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HEARING_AID);
|
||||||
|
when(mHearingAidProfile.getConnectedDevices()).thenReturn(new ArrayList<>(
|
||||||
|
Collections.singletonList(mBluetoothDevice)));
|
||||||
|
|
||||||
|
assertThat(mHelper.getConnectedHearingAidDeviceList().size()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getConnectedHearingAidDeviceList_oneSubDeviceAdded_getZeroDevice() {
|
||||||
|
mBluetoothAdapter.enable();
|
||||||
|
mShadowBluetoothAdapter.clearSupportedProfiles();
|
||||||
|
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HEARING_AID);
|
||||||
|
when(mHearingAidProfile.getConnectedDevices()).thenReturn(new ArrayList<>(
|
||||||
|
Collections.singletonList(mBluetoothDevice)));
|
||||||
|
when(mLocalBluetoothManager.getCachedDeviceManager().isSubDevice(
|
||||||
|
mBluetoothDevice)).thenReturn(true);
|
||||||
|
|
||||||
|
assertThat(mHelper.getConnectedHearingAidDeviceList().size()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getConnectedHearingAidDevice_getExpectedCachedBluetoothDevice() {
|
||||||
|
mBluetoothAdapter.enable();
|
||||||
|
mShadowBluetoothAdapter.clearSupportedProfiles();
|
||||||
|
mShadowBluetoothAdapter.addSupportedProfiles(BluetoothProfile.HEARING_AID);
|
||||||
|
when(mHearingAidProfile.getConnectedDevices()).thenReturn(new ArrayList<>(
|
||||||
|
Collections.singletonList(mBluetoothDevice)));
|
||||||
|
|
||||||
|
assertThat(mHelper.getConnectedHearingAidDevice()).isEqualTo(mCachedBluetoothDevice);
|
||||||
|
assertThat(mCachedBluetoothDevice.getAddress()).isEqualTo(mBluetoothDevice.getAddress());
|
||||||
|
}
|
||||||
|
}
|
@@ -14,13 +14,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.isNull;
|
import static org.mockito.ArgumentMatchers.isNull;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -37,9 +38,15 @@ import androidx.preference.ListPreference;
|
|||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.bluetooth.Utils;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||||
import com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants;
|
import com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants;
|
||||||
import com.android.settingslib.bluetooth.HearingAidAudioRoutingHelper;
|
import com.android.settingslib.bluetooth.HearingAidAudioRoutingHelper;
|
||||||
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
|
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@@ -50,11 +57,13 @@ import org.mockito.Spy;
|
|||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Tests for {@link HearingDeviceAudioRoutingBasePreferenceController}. */
|
/** Tests for {@link HearingDeviceAudioRoutingBasePreferenceController}. */
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(shadows = {ShadowBluetoothAdapter.class, ShadowBluetoothUtils.class})
|
||||||
public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
|
public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
@@ -63,8 +72,14 @@ public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
|
|||||||
@Spy
|
@Spy
|
||||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
|
private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
|
||||||
private static final String FAKE_KEY = "fake_key";
|
private final ListPreference mListPreference = new ListPreference(mContext);
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private LocalBluetoothManager mLocalBluetoothManager;
|
||||||
|
@Mock
|
||||||
|
private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
|
||||||
|
@Mock
|
||||||
|
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
||||||
@Mock
|
@Mock
|
||||||
private AudioProductStrategy mAudioProductStrategyMedia;
|
private AudioProductStrategy mAudioProductStrategyMedia;
|
||||||
@Mock
|
@Mock
|
||||||
@@ -72,8 +87,10 @@ public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private BluetoothDevice mBluetoothDevice;
|
private BluetoothDevice mBluetoothDevice;
|
||||||
@Spy
|
@Spy
|
||||||
private HearingAidAudioRoutingHelper mHelper = new HearingAidAudioRoutingHelper(mContext);
|
private HearingAidAudioRoutingHelper mAudioRoutingHelper =
|
||||||
private final ListPreference mListPreference = new ListPreference(mContext);
|
new HearingAidAudioRoutingHelper(mContext);
|
||||||
|
@Mock
|
||||||
|
private HearingAidHelper mHearingAidHelper;
|
||||||
private TestHearingDeviceAudioRoutingBasePreferenceController mController;
|
private TestHearingDeviceAudioRoutingBasePreferenceController mController;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -83,19 +100,23 @@ public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
|
|||||||
AudioDeviceInfo.TYPE_HEARING_AID,
|
AudioDeviceInfo.TYPE_HEARING_AID,
|
||||||
TEST_DEVICE_ADDRESS);
|
TEST_DEVICE_ADDRESS);
|
||||||
|
|
||||||
|
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
|
||||||
|
mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
|
||||||
|
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
|
||||||
|
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
|
||||||
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
|
||||||
when(mBluetoothDevice.getAnonymizedAddress()).thenReturn(TEST_DEVICE_ADDRESS);
|
when(mBluetoothDevice.getAnonymizedAddress()).thenReturn(TEST_DEVICE_ADDRESS);
|
||||||
when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
|
when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
|
||||||
when(mHelper.getMatchedHearingDeviceAttributes(any())).thenReturn(hearingDeviceAttribute);
|
doReturn(hearingDeviceAttribute).when(
|
||||||
|
mAudioRoutingHelper).getMatchedHearingDeviceAttributes(any());
|
||||||
when(mAudioProductStrategyMedia.getAudioAttributesForLegacyStreamType(
|
when(mAudioProductStrategyMedia.getAudioAttributesForLegacyStreamType(
|
||||||
AudioManager.STREAM_MUSIC))
|
AudioManager.STREAM_MUSIC)).thenReturn((new AudioAttributes.Builder()).build());
|
||||||
.thenReturn((new AudioAttributes.Builder()).build());
|
when(mAudioRoutingHelper.getAudioProductStrategies()).thenReturn(
|
||||||
when(mHelper.getAudioProductStrategies()).thenReturn(List.of(mAudioProductStrategyMedia));
|
List.of(mAudioProductStrategyMedia));
|
||||||
|
|
||||||
mController = new TestHearingDeviceAudioRoutingBasePreferenceController(mContext, FAKE_KEY,
|
mController = new TestHearingDeviceAudioRoutingBasePreferenceController(mContext,
|
||||||
mHelper);
|
"test_key",
|
||||||
TestHearingDeviceAudioRoutingBasePreferenceController.setupForTesting(
|
mAudioRoutingHelper, mHearingAidHelper);
|
||||||
mCachedBluetoothDevice);
|
|
||||||
mListPreference.setEntries(R.array.bluetooth_audio_routing_titles);
|
mListPreference.setEntries(R.array.bluetooth_audio_routing_titles);
|
||||||
mListPreference.setEntryValues(R.array.bluetooth_audio_routing_values);
|
mListPreference.setEntryValues(R.array.bluetooth_audio_routing_values);
|
||||||
mListPreference.setSummary("%s");
|
mListPreference.setSummary("%s");
|
||||||
@@ -122,20 +143,21 @@ public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onPreferenceChange_noMatchedDeviceAttributes_notCallSetStrategies() {
|
public void onPreferenceChange_noMatchedDeviceAttributes_notCallSetStrategies() {
|
||||||
when(mHelper.getMatchedHearingDeviceAttributes(any())).thenReturn(null);
|
when(mAudioRoutingHelper.getMatchedHearingDeviceAttributes(any())).thenReturn(null);
|
||||||
|
|
||||||
verify(mHelper, never()).setPreferredDeviceRoutingStrategies(any(), isNull(), anyInt());
|
verify(mAudioRoutingHelper, never()).setPreferredDeviceRoutingStrategies(any(), isNull(),
|
||||||
|
anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TestHearingDeviceAudioRoutingBasePreferenceController extends
|
private static class TestHearingDeviceAudioRoutingBasePreferenceController extends
|
||||||
HearingDeviceAudioRoutingBasePreferenceController {
|
HearingDeviceAudioRoutingBasePreferenceController {
|
||||||
|
|
||||||
private static CachedBluetoothDevice sCachedBluetoothDevice;
|
|
||||||
private static int sSavedRoutingValue;
|
private static int sSavedRoutingValue;
|
||||||
|
|
||||||
TestHearingDeviceAudioRoutingBasePreferenceController(Context context,
|
TestHearingDeviceAudioRoutingBasePreferenceController(Context context,
|
||||||
String preferenceKey, HearingAidAudioRoutingHelper helper) {
|
String preferenceKey, HearingAidAudioRoutingHelper audioRoutingHelper,
|
||||||
super(context, preferenceKey, helper);
|
HearingAidHelper hearingAidHelper) {
|
||||||
|
super(context, preferenceKey, audioRoutingHelper, hearingAidHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -143,11 +165,6 @@ public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
|
|||||||
return new int[]{AudioAttributes.USAGE_MEDIA};
|
return new int[]{AudioAttributes.USAGE_MEDIA};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected CachedBluetoothDevice getHearingDevice() {
|
|
||||||
return sCachedBluetoothDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void saveRoutingValue(Context context, int routingValue) {
|
protected void saveRoutingValue(Context context, int routingValue) {
|
||||||
sSavedRoutingValue = routingValue;
|
sSavedRoutingValue = routingValue;
|
||||||
@@ -157,9 +174,5 @@ public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
|
|||||||
protected int restoreRoutingValue(Context context) {
|
protected int restoreRoutingValue(Context context) {
|
||||||
return sSavedRoutingValue;
|
return sSavedRoutingValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setupForTesting(CachedBluetoothDevice cachedBluetoothDevice) {
|
|
||||||
sCachedBluetoothDevice = cachedBluetoothDevice;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||||
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
|
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
|
@@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2022 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
|
||||||
|
|
||||||
import static com.android.settings.bluetooth.BluetoothDetailsAudioRoutingController.KEY_AUDIO_ROUTING;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import android.util.FeatureFlagUtils;
|
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceCategory;
|
|
||||||
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.junit.MockitoJUnit;
|
|
||||||
import org.mockito.junit.MockitoRule;
|
|
||||||
import org.robolectric.RobolectricTestRunner;
|
|
||||||
|
|
||||||
/** Tests for {@link BluetoothDetailsAudioRoutingController}. */
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
|
||||||
public class BluetoothDetailsAudioRoutingControllerTest extends
|
|
||||||
BluetoothDetailsControllerTestBase {
|
|
||||||
@Rule
|
|
||||||
public final MockitoRule mockito = MockitoJUnit.rule();
|
|
||||||
|
|
||||||
private static final String TEST_ADDRESS = "55:66:77:88:99:AA";
|
|
||||||
|
|
||||||
private BluetoothDetailsAudioRoutingController mController;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUp() {
|
|
||||||
super.setUp();
|
|
||||||
|
|
||||||
mController = new BluetoothDetailsAudioRoutingController(mContext, mFragment, mCachedDevice,
|
|
||||||
mLifecycle);
|
|
||||||
final PreferenceCategory preferenceCategory = new PreferenceCategory(mContext);
|
|
||||||
preferenceCategory.setKey(mController.getPreferenceKey());
|
|
||||||
mScreen.addPreference(preferenceCategory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isAvailable_isHearingAidDevice_available() {
|
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_AUDIO_ROUTING, true);
|
|
||||||
when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
|
|
||||||
|
|
||||||
assertThat(mController.isAvailable()).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isAvailable_isNotHearingAidDevice_notAvailable() {
|
|
||||||
FeatureFlagUtils.setEnabled(mContext,
|
|
||||||
FeatureFlagUtils.SETTINGS_AUDIO_ROUTING, true);
|
|
||||||
when(mCachedDevice.isHearingAidDevice()).thenReturn(false);
|
|
||||||
|
|
||||||
assertThat(mController.isAvailable()).isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void init_isHearingAidDevice_expectedAudioRoutingPreference() {
|
|
||||||
when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
|
|
||||||
when(mCachedDevice.getAddress()).thenReturn(TEST_ADDRESS);
|
|
||||||
|
|
||||||
mController.init(mScreen);
|
|
||||||
final Preference preference = mScreen.findPreference(KEY_AUDIO_ROUTING);
|
|
||||||
final String address = preference.getExtras().getString(
|
|
||||||
BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS);
|
|
||||||
final String fragment = preference.getFragment();
|
|
||||||
|
|
||||||
assertThat(address).isEqualTo(TEST_ADDRESS);
|
|
||||||
assertThat(fragment).isEqualTo(BluetoothDetailsAudioRoutingFragment.class.getName());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2023 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.settings.bluetooth;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
|
||||||
|
|
||||||
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
|
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.MockitoJUnit;
|
|
||||||
import org.mockito.junit.MockitoRule;
|
|
||||||
import org.robolectric.RobolectricTestRunner;
|
|
||||||
import org.robolectric.annotation.Config;
|
|
||||||
|
|
||||||
/** Tests for {@link BluetoothDetailsAudioRoutingFragment}. */
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
|
||||||
@Config(shadows = {ShadowBluetoothUtils.class})
|
|
||||||
public class BluetoothDetailsAudioRoutingFragmentTest {
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public MockitoRule mMockitoRule = MockitoJUnit.rule();
|
|
||||||
|
|
||||||
private static final String TEST_ADDRESS = "55:66:77:88:99:AA";
|
|
||||||
|
|
||||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
|
||||||
|
|
||||||
private BluetoothDetailsAudioRoutingFragment mFragment;
|
|
||||||
@Mock
|
|
||||||
private LocalBluetoothManager mLocalBluetoothManager;
|
|
||||||
@Mock
|
|
||||||
private CachedBluetoothDeviceManager mCachedDeviceManager;
|
|
||||||
@Mock
|
|
||||||
private LocalBluetoothAdapter mLocalBluetoothAdapter;
|
|
||||||
@Mock
|
|
||||||
private BluetoothDevice mBluetoothDevice;
|
|
||||||
@Mock
|
|
||||||
private CachedBluetoothDevice mCachedDevice;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
setupEnvironment();
|
|
||||||
|
|
||||||
when(mLocalBluetoothAdapter.getRemoteDevice(TEST_ADDRESS)).thenReturn(mBluetoothDevice);
|
|
||||||
when(mCachedDevice.getAddress()).thenReturn(TEST_ADDRESS);
|
|
||||||
when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice);
|
|
||||||
|
|
||||||
mFragment = new BluetoothDetailsAudioRoutingFragment();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onAttach_setArgumentsWithAddress_expectedCachedDeviceWithAddress() {
|
|
||||||
final Bundle args = new Bundle();
|
|
||||||
args.putString(BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS, TEST_ADDRESS);
|
|
||||||
mFragment.setArguments(args);
|
|
||||||
|
|
||||||
mFragment.onAttach(mContext);
|
|
||||||
|
|
||||||
assertThat(mFragment.mCachedDevice.getAddress()).isEqualTo(TEST_ADDRESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupEnvironment() {
|
|
||||||
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
|
|
||||||
when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
|
|
||||||
when(mLocalBluetoothManager.getBluetoothAdapter()).thenReturn(mLocalBluetoothAdapter);
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user