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:
jasonwshsu
2023-05-11 20:25:10 +08:00
parent 6619994919
commit 212470d0a6
25 changed files with 542 additions and 619 deletions

View File

@@ -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 &amp; 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] -->

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"/>

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;
}
}

View 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;
}
}

View File

@@ -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.
* *

View File

@@ -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(),

View File

@@ -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(),

View File

@@ -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(),

View File

@@ -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(),

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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(

View File

@@ -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);
}
}

View File

@@ -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());
}
}

View File

@@ -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;
}
} }
} }

View File

@@ -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;

View File

@@ -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());
}
}

View File

@@ -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);
}
}