Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidAudioRoutingConstants.java +9 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.settingslib.bluetooth; import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceInfo; import android.media.MediaRecorder; import androidx.annotation.IntDef; Loading Loading @@ -61,15 +62,20 @@ public final class HearingAidAudioRoutingConstants { @IntDef({ RoutingValue.AUTO, RoutingValue.HEARING_DEVICE, RoutingValue.DEVICE_SPEAKER, RoutingValue.BUILTIN_DEVICE, }) public @interface RoutingValue { int AUTO = 0; int HEARING_DEVICE = 1; int DEVICE_SPEAKER = 2; int BUILTIN_DEVICE = 2; } public static final AudioDeviceAttributes DEVICE_SPEAKER_OUT = new AudioDeviceAttributes( public static final AudioDeviceAttributes BUILTIN_SPEAKER = new AudioDeviceAttributes( AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, ""); public static final AudioDeviceAttributes BUILTIN_MIC = new AudioDeviceAttributes( AudioDeviceAttributes.ROLE_INPUT, AudioDeviceInfo.TYPE_BUILTIN_MIC, ""); public static final int MICROPHONE_SOURCE_VOICE_COMMUNICATION = MediaRecorder.AudioSource.VOICE_COMMUNICATION; } packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidAudioRoutingHelper.java +102 −11 Original line number Diff line number Diff line Loading @@ -16,26 +16,34 @@ package com.android.settingslib.bluetooth; import static com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants.BUILTIN_MIC; import static com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants.MICROPHONE_SOURCE_VOICE_COMMUNICATION; import android.content.Context; import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.media.audiopolicy.AudioProductStrategy; import android.util.Log; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants.RoutingValue; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * A helper class to configure the routing strategy for hearing aids. * A helper class to configure the audio routing for hearing aids. */ public class HearingAidAudioRoutingHelper { private static final String TAG = "HearingAidAudioRoutingHelper"; private final AudioManager mAudioManager; public HearingAidAudioRoutingHelper(Context context) { Loading Loading @@ -73,26 +81,26 @@ public class HearingAidAudioRoutingHelper { * @param hearingDevice {@link AudioDeviceAttributes} of the device to be changed in audio * routing * @param routingValue one of value defined in * {@link HearingAidAudioRoutingConstants.RoutingValue}, denotes routing * {@link RoutingValue}, denotes routing * destination. * @return {code true} if the routing value successfully configure */ public boolean setPreferredDeviceRoutingStrategies( List<AudioProductStrategy> supportedStrategies, AudioDeviceAttributes hearingDevice, @HearingAidAudioRoutingConstants.RoutingValue int routingValue) { @RoutingValue int routingValue) { boolean status; switch (routingValue) { case HearingAidAudioRoutingConstants.RoutingValue.AUTO: case RoutingValue.AUTO: status = removePreferredDeviceForStrategies(supportedStrategies); return status; case HearingAidAudioRoutingConstants.RoutingValue.HEARING_DEVICE: case RoutingValue.HEARING_DEVICE: status = removePreferredDeviceForStrategies(supportedStrategies); status &= setPreferredDeviceForStrategies(supportedStrategies, hearingDevice); return status; case HearingAidAudioRoutingConstants.RoutingValue.DEVICE_SPEAKER: case RoutingValue.BUILTIN_DEVICE: status = removePreferredDeviceForStrategies(supportedStrategies); status &= setPreferredDeviceForStrategies(supportedStrategies, HearingAidAudioRoutingConstants.DEVICE_SPEAKER_OUT); HearingAidAudioRoutingConstants.BUILTIN_SPEAKER); return status; default: throw new IllegalArgumentException("Unexpected routingValue: " + routingValue); Loading @@ -100,21 +108,76 @@ public class HearingAidAudioRoutingHelper { } /** * Gets the matched hearing device {@link AudioDeviceAttributes} for {@code device}. * Set the preferred input device for calls. * * <p>Will also try to match the {@link CachedBluetoothDevice#getSubDevice()} of {@code device} * <p>Note that hearing device needs to be valid input device to be found in AudioManager. * <p>Routing value can be: * <ul> * <li> {@link RoutingValue#AUTO} - Allow the system to automatically select the appropriate * audio routing for calls.</li> * <li> {@link RoutingValue#HEARING_DEVICE} - Set input device to this hearing device.</li> * <li> {@link RoutingValue#BUILTIN_DEVICE} - Set input device to builtin microphone. </li> * </ul> * @param routingValue The desired routing value for calls * @return {@code true} if the operation was successful */ public boolean setPreferredInputDeviceForCalls(@Nullable CachedBluetoothDevice hearingDevice, @RoutingValue int routingValue) { AudioDeviceAttributes hearingDeviceAttributes = getMatchedHearingDeviceAttributesInput( hearingDevice); if (hearingDeviceAttributes == null) { Log.w(TAG, "Can not find expected input AudioDeviceAttributes for hearing device: " + hearingDevice.getDevice().getAnonymizedAddress()); return false; } final int audioSource = MICROPHONE_SOURCE_VOICE_COMMUNICATION; return switch (routingValue) { case RoutingValue.AUTO -> mAudioManager.clearPreferredDevicesForCapturePreset(audioSource); case RoutingValue.HEARING_DEVICE -> { mAudioManager.clearPreferredDevicesForCapturePreset(audioSource); yield mAudioManager.setPreferredDeviceForCapturePreset(audioSource, hearingDeviceAttributes); } case RoutingValue.BUILTIN_DEVICE -> { mAudioManager.clearPreferredDevicesForCapturePreset(audioSource); yield mAudioManager.setPreferredDeviceForCapturePreset(audioSource, BUILTIN_MIC); } default -> throw new IllegalArgumentException( "Unexpected routingValue: " + routingValue); }; } /** * Clears the preferred input device for calls. * * {@code true} if the operation was successful */ public boolean clearPreferredInputDeviceForCalls() { return mAudioManager.clearPreferredDevicesForCapturePreset( MICROPHONE_SOURCE_VOICE_COMMUNICATION); } /** * Gets the matched output hearing device {@link AudioDeviceAttributes} for {@code device}. * * <p>Will also try to match the {@link CachedBluetoothDevice#getSubDevice()} and * {@link CachedBluetoothDevice#getMemberDevice()} of {@code device} * * @param device the {@link CachedBluetoothDevice} need to be hearing aid device * @return the requested AudioDeviceAttributes or {@code null} if not match */ @Nullable public AudioDeviceAttributes getMatchedHearingDeviceAttributes(CachedBluetoothDevice device) { public AudioDeviceAttributes getMatchedHearingDeviceAttributesForOutput( @Nullable CachedBluetoothDevice device) { if (device == null || !device.isHearingAidDevice()) { return null; } AudioDeviceInfo[] audioDevices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS); for (AudioDeviceInfo audioDevice : audioDevices) { //TODO: b/370812132 - Need to update if TYPE_LEA_HEARING_AID is added // ASHA for TYPE_HEARING_AID, HAP for TYPE_BLE_HEADSET if (audioDevice.getType() == AudioDeviceInfo.TYPE_HEARING_AID || audioDevice.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET) { Loading @@ -126,6 +189,35 @@ public class HearingAidAudioRoutingHelper { return null; } /** * Gets the matched input hearing device {@link AudioDeviceAttributes} for {@code device}. * * <p>Will also try to match the {@link CachedBluetoothDevice#getSubDevice()} and * {@link CachedBluetoothDevice#getMemberDevice()} of {@code device} * * @param device the {@link CachedBluetoothDevice} need to be hearing aid device * @return the requested AudioDeviceAttributes or {@code null} if not match */ @Nullable private AudioDeviceAttributes getMatchedHearingDeviceAttributesInput( @Nullable CachedBluetoothDevice device) { if (device == null || !device.isHearingAidDevice()) { return null; } AudioDeviceInfo[] audioDevices = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS); for (AudioDeviceInfo audioDevice : audioDevices) { //TODO: b/370812132 - Need to update if TYPE_LEA_HEARING_AID is added // HAP for TYPE_BLE_HEADSET if (audioDevice.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET) { if (matchAddress(device, audioDevice)) { return new AudioDeviceAttributes(audioDevice); } } } return null; } private boolean matchAddress(CachedBluetoothDevice device, AudioDeviceInfo audioDevice) { final String audioDeviceAddress = audioDevice.getAddress(); final CachedBluetoothDevice subDevice = device.getSubDevice(); Loading @@ -142,7 +234,6 @@ public class HearingAidAudioRoutingHelper { boolean status = true; for (AudioProductStrategy strategy : strategies) { status &= mAudioManager.setPreferredDeviceForStrategy(strategy, audioDevice); } return status; Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java +35 −16 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.util.FeatureFlagUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants.RoutingValue; import java.util.HashSet; import java.util.List; Loading Loading @@ -277,13 +278,19 @@ public class HearingAidDeviceManager { void onActiveDeviceChanged(CachedBluetoothDevice device) { if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_AUDIO_ROUTING)) { if (device.isActiveDevice(BluetoothProfile.HEARING_AID) || device.isActiveDevice( BluetoothProfile.LE_AUDIO)) { if (device.isConnectedHearingAidDevice()) { setAudioRoutingConfig(device); } else { clearAudioRoutingConfig(); } } if (com.android.settingslib.flags.Flags.hearingDevicesInputRoutingControl()) { if (device.isConnectedHearingAidDevice()) { setMicrophoneForCalls(device); } else { clearMicrophoneForCalls(); } } } void syncDeviceIfNeeded(CachedBluetoothDevice device) { Loading Loading @@ -311,9 +318,25 @@ public class HearingAidDeviceManager { HearingDeviceLocalDataManager.clear(mContext, device.getDevice()); } private void setMicrophoneForCalls(CachedBluetoothDevice device) { boolean useRemoteMicrophone = device.getDevice().isMicrophonePreferredForCalls(); boolean status = mRoutingHelper.setPreferredInputDeviceForCalls(device, useRemoteMicrophone ? RoutingValue.AUTO : RoutingValue.BUILTIN_DEVICE); if (!status) { Log.d(TAG, "Fail to configure setPreferredInputDeviceForCalls"); } } private void clearMicrophoneForCalls() { boolean status = mRoutingHelper.clearPreferredInputDeviceForCalls(); if (!status) { Log.d(TAG, "Fail to configure clearMicrophoneForCalls"); } } private void setAudioRoutingConfig(CachedBluetoothDevice device) { AudioDeviceAttributes hearingDeviceAttributes = mRoutingHelper.getMatchedHearingDeviceAttributes(device); mRoutingHelper.getMatchedHearingDeviceAttributesForOutput(device); if (hearingDeviceAttributes == null) { Log.w(TAG, "Can not find expected AudioDeviceAttributes for hearing device: " + device.getDevice().getAnonymizedAddress()); Loading @@ -321,17 +344,13 @@ public class HearingAidDeviceManager { } final int callRoutingValue = Settings.Secure.getInt(mContentResolver, Settings.Secure.HEARING_AID_CALL_ROUTING, HearingAidAudioRoutingConstants.RoutingValue.AUTO); Settings.Secure.HEARING_AID_CALL_ROUTING, RoutingValue.AUTO); final int mediaRoutingValue = Settings.Secure.getInt(mContentResolver, Settings.Secure.HEARING_AID_MEDIA_ROUTING, HearingAidAudioRoutingConstants.RoutingValue.AUTO); Settings.Secure.HEARING_AID_MEDIA_ROUTING, RoutingValue.AUTO); final int ringtoneRoutingValue = Settings.Secure.getInt(mContentResolver, Settings.Secure.HEARING_AID_RINGTONE_ROUTING, HearingAidAudioRoutingConstants.RoutingValue.AUTO); Settings.Secure.HEARING_AID_RINGTONE_ROUTING, RoutingValue.AUTO); final int systemSoundsRoutingValue = Settings.Secure.getInt(mContentResolver, Settings.Secure.HEARING_AID_NOTIFICATION_ROUTING, HearingAidAudioRoutingConstants.RoutingValue.AUTO); Settings.Secure.HEARING_AID_NOTIFICATION_ROUTING, RoutingValue.AUTO); setPreferredDeviceRoutingStrategies( HearingAidAudioRoutingConstants.CALL_ROUTING_ATTRIBUTES, Loading @@ -351,21 +370,21 @@ public class HearingAidDeviceManager { // Don't need to pass hearingDevice when we want to reset it (set to AUTO). setPreferredDeviceRoutingStrategies( HearingAidAudioRoutingConstants.CALL_ROUTING_ATTRIBUTES, /* hearingDevice = */ null, HearingAidAudioRoutingConstants.RoutingValue.AUTO); /* hearingDevice = */ null, RoutingValue.AUTO); setPreferredDeviceRoutingStrategies( HearingAidAudioRoutingConstants.MEDIA_ROUTING_ATTRIBUTES, /* hearingDevice = */ null, HearingAidAudioRoutingConstants.RoutingValue.AUTO); /* hearingDevice = */ null, RoutingValue.AUTO); setPreferredDeviceRoutingStrategies( HearingAidAudioRoutingConstants.RINGTONE_ROUTING_ATTRIBUTES, /* hearingDevice = */ null, HearingAidAudioRoutingConstants.RoutingValue.AUTO); /* hearingDevice = */ null, RoutingValue.AUTO); setPreferredDeviceRoutingStrategies( HearingAidAudioRoutingConstants.NOTIFICATION_ROUTING_ATTRIBUTES, /* hearingDevice = */ null, HearingAidAudioRoutingConstants.RoutingValue.AUTO); /* hearingDevice = */ null, RoutingValue.AUTO); } private void setPreferredDeviceRoutingStrategies(int[] attributeSdkUsageList, AudioDeviceAttributes hearingDevice, @HearingAidAudioRoutingConstants.RoutingValue int routingValue) { @RoutingValue int routingValue) { final List<AudioProductStrategy> supportedStrategies = mRoutingHelper.getSupportedStrategies(attributeSdkUsageList); Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidAudioRoutingHelperTest.java +75 −30 File changed.Preview size limit exceeded, changes collapsed. Show changes packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -729,7 +729,7 @@ public class HearingAidDeviceManagerTest { @Test public void onActiveDeviceChanged_connected_callSetStrategies() { when(mHelper.getMatchedHearingDeviceAttributes(mCachedDevice1)).thenReturn( when(mHelper.getMatchedHearingDeviceAttributesForOutput(mCachedDevice1)).thenReturn( mHearingDeviceAttribute); when(mCachedDevice1.isActiveDevice(BluetoothProfile.HEARING_AID)).thenReturn(true); doReturn(true).when(mHelper).setPreferredDeviceRoutingStrategies(anyList(), Loading @@ -743,7 +743,7 @@ public class HearingAidDeviceManagerTest { @Test public void onActiveDeviceChanged_disconnected_callSetStrategiesWithAutoValue() { when(mHelper.getMatchedHearingDeviceAttributes(mCachedDevice1)).thenReturn( when(mHelper.getMatchedHearingDeviceAttributesForOutput(mCachedDevice1)).thenReturn( mHearingDeviceAttribute); when(mCachedDevice1.isActiveDevice(BluetoothProfile.HEARING_AID)).thenReturn(false); doReturn(true).when(mHelper).setPreferredDeviceRoutingStrategies(anyList(), any(), Loading Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidAudioRoutingConstants.java +9 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.settingslib.bluetooth; import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceInfo; import android.media.MediaRecorder; import androidx.annotation.IntDef; Loading Loading @@ -61,15 +62,20 @@ public final class HearingAidAudioRoutingConstants { @IntDef({ RoutingValue.AUTO, RoutingValue.HEARING_DEVICE, RoutingValue.DEVICE_SPEAKER, RoutingValue.BUILTIN_DEVICE, }) public @interface RoutingValue { int AUTO = 0; int HEARING_DEVICE = 1; int DEVICE_SPEAKER = 2; int BUILTIN_DEVICE = 2; } public static final AudioDeviceAttributes DEVICE_SPEAKER_OUT = new AudioDeviceAttributes( public static final AudioDeviceAttributes BUILTIN_SPEAKER = new AudioDeviceAttributes( AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, ""); public static final AudioDeviceAttributes BUILTIN_MIC = new AudioDeviceAttributes( AudioDeviceAttributes.ROLE_INPUT, AudioDeviceInfo.TYPE_BUILTIN_MIC, ""); public static final int MICROPHONE_SOURCE_VOICE_COMMUNICATION = MediaRecorder.AudioSource.VOICE_COMMUNICATION; }
packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidAudioRoutingHelper.java +102 −11 Original line number Diff line number Diff line Loading @@ -16,26 +16,34 @@ package com.android.settingslib.bluetooth; import static com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants.BUILTIN_MIC; import static com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants.MICROPHONE_SOURCE_VOICE_COMMUNICATION; import android.content.Context; import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.media.audiopolicy.AudioProductStrategy; import android.util.Log; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants.RoutingValue; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * A helper class to configure the routing strategy for hearing aids. * A helper class to configure the audio routing for hearing aids. */ public class HearingAidAudioRoutingHelper { private static final String TAG = "HearingAidAudioRoutingHelper"; private final AudioManager mAudioManager; public HearingAidAudioRoutingHelper(Context context) { Loading Loading @@ -73,26 +81,26 @@ public class HearingAidAudioRoutingHelper { * @param hearingDevice {@link AudioDeviceAttributes} of the device to be changed in audio * routing * @param routingValue one of value defined in * {@link HearingAidAudioRoutingConstants.RoutingValue}, denotes routing * {@link RoutingValue}, denotes routing * destination. * @return {code true} if the routing value successfully configure */ public boolean setPreferredDeviceRoutingStrategies( List<AudioProductStrategy> supportedStrategies, AudioDeviceAttributes hearingDevice, @HearingAidAudioRoutingConstants.RoutingValue int routingValue) { @RoutingValue int routingValue) { boolean status; switch (routingValue) { case HearingAidAudioRoutingConstants.RoutingValue.AUTO: case RoutingValue.AUTO: status = removePreferredDeviceForStrategies(supportedStrategies); return status; case HearingAidAudioRoutingConstants.RoutingValue.HEARING_DEVICE: case RoutingValue.HEARING_DEVICE: status = removePreferredDeviceForStrategies(supportedStrategies); status &= setPreferredDeviceForStrategies(supportedStrategies, hearingDevice); return status; case HearingAidAudioRoutingConstants.RoutingValue.DEVICE_SPEAKER: case RoutingValue.BUILTIN_DEVICE: status = removePreferredDeviceForStrategies(supportedStrategies); status &= setPreferredDeviceForStrategies(supportedStrategies, HearingAidAudioRoutingConstants.DEVICE_SPEAKER_OUT); HearingAidAudioRoutingConstants.BUILTIN_SPEAKER); return status; default: throw new IllegalArgumentException("Unexpected routingValue: " + routingValue); Loading @@ -100,21 +108,76 @@ public class HearingAidAudioRoutingHelper { } /** * Gets the matched hearing device {@link AudioDeviceAttributes} for {@code device}. * Set the preferred input device for calls. * * <p>Will also try to match the {@link CachedBluetoothDevice#getSubDevice()} of {@code device} * <p>Note that hearing device needs to be valid input device to be found in AudioManager. * <p>Routing value can be: * <ul> * <li> {@link RoutingValue#AUTO} - Allow the system to automatically select the appropriate * audio routing for calls.</li> * <li> {@link RoutingValue#HEARING_DEVICE} - Set input device to this hearing device.</li> * <li> {@link RoutingValue#BUILTIN_DEVICE} - Set input device to builtin microphone. </li> * </ul> * @param routingValue The desired routing value for calls * @return {@code true} if the operation was successful */ public boolean setPreferredInputDeviceForCalls(@Nullable CachedBluetoothDevice hearingDevice, @RoutingValue int routingValue) { AudioDeviceAttributes hearingDeviceAttributes = getMatchedHearingDeviceAttributesInput( hearingDevice); if (hearingDeviceAttributes == null) { Log.w(TAG, "Can not find expected input AudioDeviceAttributes for hearing device: " + hearingDevice.getDevice().getAnonymizedAddress()); return false; } final int audioSource = MICROPHONE_SOURCE_VOICE_COMMUNICATION; return switch (routingValue) { case RoutingValue.AUTO -> mAudioManager.clearPreferredDevicesForCapturePreset(audioSource); case RoutingValue.HEARING_DEVICE -> { mAudioManager.clearPreferredDevicesForCapturePreset(audioSource); yield mAudioManager.setPreferredDeviceForCapturePreset(audioSource, hearingDeviceAttributes); } case RoutingValue.BUILTIN_DEVICE -> { mAudioManager.clearPreferredDevicesForCapturePreset(audioSource); yield mAudioManager.setPreferredDeviceForCapturePreset(audioSource, BUILTIN_MIC); } default -> throw new IllegalArgumentException( "Unexpected routingValue: " + routingValue); }; } /** * Clears the preferred input device for calls. * * {@code true} if the operation was successful */ public boolean clearPreferredInputDeviceForCalls() { return mAudioManager.clearPreferredDevicesForCapturePreset( MICROPHONE_SOURCE_VOICE_COMMUNICATION); } /** * Gets the matched output hearing device {@link AudioDeviceAttributes} for {@code device}. * * <p>Will also try to match the {@link CachedBluetoothDevice#getSubDevice()} and * {@link CachedBluetoothDevice#getMemberDevice()} of {@code device} * * @param device the {@link CachedBluetoothDevice} need to be hearing aid device * @return the requested AudioDeviceAttributes or {@code null} if not match */ @Nullable public AudioDeviceAttributes getMatchedHearingDeviceAttributes(CachedBluetoothDevice device) { public AudioDeviceAttributes getMatchedHearingDeviceAttributesForOutput( @Nullable CachedBluetoothDevice device) { if (device == null || !device.isHearingAidDevice()) { return null; } AudioDeviceInfo[] audioDevices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS); for (AudioDeviceInfo audioDevice : audioDevices) { //TODO: b/370812132 - Need to update if TYPE_LEA_HEARING_AID is added // ASHA for TYPE_HEARING_AID, HAP for TYPE_BLE_HEADSET if (audioDevice.getType() == AudioDeviceInfo.TYPE_HEARING_AID || audioDevice.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET) { Loading @@ -126,6 +189,35 @@ public class HearingAidAudioRoutingHelper { return null; } /** * Gets the matched input hearing device {@link AudioDeviceAttributes} for {@code device}. * * <p>Will also try to match the {@link CachedBluetoothDevice#getSubDevice()} and * {@link CachedBluetoothDevice#getMemberDevice()} of {@code device} * * @param device the {@link CachedBluetoothDevice} need to be hearing aid device * @return the requested AudioDeviceAttributes or {@code null} if not match */ @Nullable private AudioDeviceAttributes getMatchedHearingDeviceAttributesInput( @Nullable CachedBluetoothDevice device) { if (device == null || !device.isHearingAidDevice()) { return null; } AudioDeviceInfo[] audioDevices = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS); for (AudioDeviceInfo audioDevice : audioDevices) { //TODO: b/370812132 - Need to update if TYPE_LEA_HEARING_AID is added // HAP for TYPE_BLE_HEADSET if (audioDevice.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET) { if (matchAddress(device, audioDevice)) { return new AudioDeviceAttributes(audioDevice); } } } return null; } private boolean matchAddress(CachedBluetoothDevice device, AudioDeviceInfo audioDevice) { final String audioDeviceAddress = audioDevice.getAddress(); final CachedBluetoothDevice subDevice = device.getSubDevice(); Loading @@ -142,7 +234,6 @@ public class HearingAidAudioRoutingHelper { boolean status = true; for (AudioProductStrategy strategy : strategies) { status &= mAudioManager.setPreferredDeviceForStrategy(strategy, audioDevice); } return status; Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java +35 −16 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.util.FeatureFlagUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants.RoutingValue; import java.util.HashSet; import java.util.List; Loading Loading @@ -277,13 +278,19 @@ public class HearingAidDeviceManager { void onActiveDeviceChanged(CachedBluetoothDevice device) { if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_AUDIO_ROUTING)) { if (device.isActiveDevice(BluetoothProfile.HEARING_AID) || device.isActiveDevice( BluetoothProfile.LE_AUDIO)) { if (device.isConnectedHearingAidDevice()) { setAudioRoutingConfig(device); } else { clearAudioRoutingConfig(); } } if (com.android.settingslib.flags.Flags.hearingDevicesInputRoutingControl()) { if (device.isConnectedHearingAidDevice()) { setMicrophoneForCalls(device); } else { clearMicrophoneForCalls(); } } } void syncDeviceIfNeeded(CachedBluetoothDevice device) { Loading Loading @@ -311,9 +318,25 @@ public class HearingAidDeviceManager { HearingDeviceLocalDataManager.clear(mContext, device.getDevice()); } private void setMicrophoneForCalls(CachedBluetoothDevice device) { boolean useRemoteMicrophone = device.getDevice().isMicrophonePreferredForCalls(); boolean status = mRoutingHelper.setPreferredInputDeviceForCalls(device, useRemoteMicrophone ? RoutingValue.AUTO : RoutingValue.BUILTIN_DEVICE); if (!status) { Log.d(TAG, "Fail to configure setPreferredInputDeviceForCalls"); } } private void clearMicrophoneForCalls() { boolean status = mRoutingHelper.clearPreferredInputDeviceForCalls(); if (!status) { Log.d(TAG, "Fail to configure clearMicrophoneForCalls"); } } private void setAudioRoutingConfig(CachedBluetoothDevice device) { AudioDeviceAttributes hearingDeviceAttributes = mRoutingHelper.getMatchedHearingDeviceAttributes(device); mRoutingHelper.getMatchedHearingDeviceAttributesForOutput(device); if (hearingDeviceAttributes == null) { Log.w(TAG, "Can not find expected AudioDeviceAttributes for hearing device: " + device.getDevice().getAnonymizedAddress()); Loading @@ -321,17 +344,13 @@ public class HearingAidDeviceManager { } final int callRoutingValue = Settings.Secure.getInt(mContentResolver, Settings.Secure.HEARING_AID_CALL_ROUTING, HearingAidAudioRoutingConstants.RoutingValue.AUTO); Settings.Secure.HEARING_AID_CALL_ROUTING, RoutingValue.AUTO); final int mediaRoutingValue = Settings.Secure.getInt(mContentResolver, Settings.Secure.HEARING_AID_MEDIA_ROUTING, HearingAidAudioRoutingConstants.RoutingValue.AUTO); Settings.Secure.HEARING_AID_MEDIA_ROUTING, RoutingValue.AUTO); final int ringtoneRoutingValue = Settings.Secure.getInt(mContentResolver, Settings.Secure.HEARING_AID_RINGTONE_ROUTING, HearingAidAudioRoutingConstants.RoutingValue.AUTO); Settings.Secure.HEARING_AID_RINGTONE_ROUTING, RoutingValue.AUTO); final int systemSoundsRoutingValue = Settings.Secure.getInt(mContentResolver, Settings.Secure.HEARING_AID_NOTIFICATION_ROUTING, HearingAidAudioRoutingConstants.RoutingValue.AUTO); Settings.Secure.HEARING_AID_NOTIFICATION_ROUTING, RoutingValue.AUTO); setPreferredDeviceRoutingStrategies( HearingAidAudioRoutingConstants.CALL_ROUTING_ATTRIBUTES, Loading @@ -351,21 +370,21 @@ public class HearingAidDeviceManager { // Don't need to pass hearingDevice when we want to reset it (set to AUTO). setPreferredDeviceRoutingStrategies( HearingAidAudioRoutingConstants.CALL_ROUTING_ATTRIBUTES, /* hearingDevice = */ null, HearingAidAudioRoutingConstants.RoutingValue.AUTO); /* hearingDevice = */ null, RoutingValue.AUTO); setPreferredDeviceRoutingStrategies( HearingAidAudioRoutingConstants.MEDIA_ROUTING_ATTRIBUTES, /* hearingDevice = */ null, HearingAidAudioRoutingConstants.RoutingValue.AUTO); /* hearingDevice = */ null, RoutingValue.AUTO); setPreferredDeviceRoutingStrategies( HearingAidAudioRoutingConstants.RINGTONE_ROUTING_ATTRIBUTES, /* hearingDevice = */ null, HearingAidAudioRoutingConstants.RoutingValue.AUTO); /* hearingDevice = */ null, RoutingValue.AUTO); setPreferredDeviceRoutingStrategies( HearingAidAudioRoutingConstants.NOTIFICATION_ROUTING_ATTRIBUTES, /* hearingDevice = */ null, HearingAidAudioRoutingConstants.RoutingValue.AUTO); /* hearingDevice = */ null, RoutingValue.AUTO); } private void setPreferredDeviceRoutingStrategies(int[] attributeSdkUsageList, AudioDeviceAttributes hearingDevice, @HearingAidAudioRoutingConstants.RoutingValue int routingValue) { @RoutingValue int routingValue) { final List<AudioProductStrategy> supportedStrategies = mRoutingHelper.getSupportedStrategies(attributeSdkUsageList); Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidAudioRoutingHelperTest.java +75 −30 File changed.Preview size limit exceeded, changes collapsed. Show changes
packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -729,7 +729,7 @@ public class HearingAidDeviceManagerTest { @Test public void onActiveDeviceChanged_connected_callSetStrategies() { when(mHelper.getMatchedHearingDeviceAttributes(mCachedDevice1)).thenReturn( when(mHelper.getMatchedHearingDeviceAttributesForOutput(mCachedDevice1)).thenReturn( mHearingDeviceAttribute); when(mCachedDevice1.isActiveDevice(BluetoothProfile.HEARING_AID)).thenReturn(true); doReturn(true).when(mHelper).setPreferredDeviceRoutingStrategies(anyList(), Loading @@ -743,7 +743,7 @@ public class HearingAidDeviceManagerTest { @Test public void onActiveDeviceChanged_disconnected_callSetStrategiesWithAutoValue() { when(mHelper.getMatchedHearingDeviceAttributes(mCachedDevice1)).thenReturn( when(mHelper.getMatchedHearingDeviceAttributesForOutput(mCachedDevice1)).thenReturn( mHearingDeviceAttribute); when(mCachedDevice1.isActiveDevice(BluetoothProfile.HEARING_AID)).thenReturn(false); doReturn(true).when(mHelper).setPreferredDeviceRoutingStrategies(anyList(), any(), Loading