Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f0f0055 authored by Wenyu Zhang's avatar Wenyu Zhang
Browse files

Apply default selected device to all presets

When system is initialized, or when audio device is
connected/disconnected, the default active input device returned back
from AudioPolicyManager does not apply to all all capture presets.

This leads to an issue that the selected device shown in UI does not
match the real device used in some presets (e.g. recording), which
makes users confused. This CL fixes this problem by applying the
default selected device to all presets.

Change-Id: I80efab3db6afa41c67c671e3b6bb73666c151086
Bug: b/355684672, b/357123258
Test: InputRouteManagerTest
Flag: com.android.media.flags.enable_audio_input_device_routing_and_volume_control
parent 2f809c50
Loading
Loading
Loading
Loading
+39 −16
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioDeviceInfo.AudioDeviceType;
import android.media.AudioManager;
import android.media.MediaRecorder;
import android.os.Handler;
@@ -63,7 +64,7 @@ public final class InputRouteManager {

    @VisibleForTesting final List<MediaDevice> mInputMediaDevices = new CopyOnWriteArrayList<>();

    private MediaDevice mSelectedInputDevice;
    private @AudioDeviceType int mSelectedInputDeviceType;

    private final Collection<InputDeviceCallback> mCallbacks = new CopyOnWriteArrayList<>();
    private final Object mCallbackLock = new Object();
@@ -73,12 +74,12 @@ public final class InputRouteManager {
            new AudioDeviceCallback() {
                @Override
                public void onAudioDevicesAdded(@NonNull AudioDeviceInfo[] addedDevices) {
                    dispatchInputDeviceListUpdate();
                    applyDefaultSelectedTypeToAllPresets();
                }

                @Override
                public void onAudioDevicesRemoved(@NonNull AudioDeviceInfo[] removedDevices) {
                    dispatchInputDeviceListUpdate();
                    applyDefaultSelectedTypeToAllPresets();
                }
            };

@@ -92,9 +93,12 @@ public final class InputRouteManager {
        mAudioManager.addOnPreferredDevicesForCapturePresetChangedListener(
                new HandlerExecutor(handler),
                this::onPreferredDevicesForCapturePresetChangedListener);

        applyDefaultSelectedTypeToAllPresets();
    }

    private void onPreferredDevicesForCapturePresetChangedListener(
    @VisibleForTesting
    void onPreferredDevicesForCapturePresetChangedListener(
            @MediaRecorder.SystemSource int capturePreset,
            @NonNull List<AudioDeviceAttributes> devices) {
        if (capturePreset == MediaRecorder.AudioSource.MIC) {
@@ -117,12 +121,30 @@ public final class InputRouteManager {
        }
    }

    // TODO(b/355684672): handle edge case where there are two devices with the same type. Only
    // using a single mSelectedInputDeviceType might not be enough to recognize the correct device.
    public @Nullable MediaDevice getSelectedInputDevice() {
        return mSelectedInputDevice;
        for (MediaDevice device : mInputMediaDevices) {
            if (((InputMediaDevice) device).getAudioDeviceInfoType() == mSelectedInputDeviceType) {
                return device;
            }
        }
        return null;
    }

    private void dispatchInputDeviceListUpdate() {
        // Get selected input device.
    private void applyDefaultSelectedTypeToAllPresets() {
        mSelectedInputDeviceType = retrieveDefaultSelectedDeviceType();
        AudioDeviceAttributes deviceAttributes =
                createInputDeviceAttributes(mSelectedInputDeviceType);
        setPreferredDeviceForAllPresets(deviceAttributes);
    }

    private AudioDeviceAttributes createInputDeviceAttributes(@AudioDeviceType int type) {
        // Address is not used.
        return new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_INPUT, type, /* address= */ "");
    }

    private @AudioDeviceType int retrieveDefaultSelectedDeviceType() {
        List<AudioDeviceAttributes> attributesOfSelectedInputDevices =
                mAudioManager.getDevicesForAttributes(INPUT_ATTRIBUTES);
        int selectedInputDeviceAttributesType;
@@ -138,7 +160,10 @@ public final class InputRouteManager {
            }
            selectedInputDeviceAttributesType = attributesOfSelectedInputDevices.get(0).getType();
        }
        return selectedInputDeviceAttributesType;
    }

    private void dispatchInputDeviceListUpdate() {
        // Get all input devices.
        AudioDeviceInfo[] audioDeviceInfos =
                mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
@@ -154,9 +179,8 @@ public final class InputRouteManager {
                            isInputGainFixed(),
                            getProductNameFromAudioDeviceInfo(info));
            if (mediaDevice != null) {
                if (info.getType() == selectedInputDeviceAttributesType) {
                if (info.getType() == mSelectedInputDeviceType) {
                    mediaDevice.setState(STATE_SELECTED);
                    mSelectedInputDevice = mediaDevice;
                }
                mInputMediaDevices.add(mediaDevice);
            }
@@ -190,12 +214,12 @@ public final class InputRouteManager {
    }

    public void selectDevice(@NonNull MediaDevice device) {
        if (!(device instanceof InputMediaDevice)) {
        if (!(device instanceof InputMediaDevice inputMediaDevice)) {
            Slog.w(TAG, "This device is not an InputMediaDevice: " + device.getName());
            return;
        }

        if (device.equals(mSelectedInputDevice)) {
        if (inputMediaDevice.getAudioDeviceInfoType() == mSelectedInputDeviceType) {
            Slog.w(TAG, "This device is already selected: " + device.getName());
            return;
        }
@@ -206,12 +230,11 @@ public final class InputRouteManager {
            return;
        }

        // TODO(b/355684672): apply address for BT devices.
        // Update mSelectedInputDeviceType directly based on user action.
        mSelectedInputDeviceType = inputMediaDevice.getAudioDeviceInfoType();

        AudioDeviceAttributes deviceAttributes =
                new AudioDeviceAttributes(
                        AudioDeviceAttributes.ROLE_INPUT,
                        ((InputMediaDevice) device).getAudioDeviceInfoType(),
                        /* address= */ "");
                createInputDeviceAttributes(inputMediaDevice.getAudioDeviceInfoType());
        try {
            setPreferredDeviceForAllPresets(deviceAttributes);
        } catch (IllegalArgumentException e) {
+175 −105

File changed.

Preview size limit exceeded, changes collapsed.