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

Commit f95ed092 authored by ryanywlin's avatar ryanywlin Committed by android-build-merger
Browse files

Merge changes from topic "add-hearing-aid-device-in-audio-switch" into pi-dev am: 7e31e22f

am: 82db752e

Change-Id: I7e9a40b08afebedb7b44a6345cda8b2564db315d
parents c1884b7c 82db752e
Loading
Loading
Loading
Loading
+107 −6
Original line number Diff line number Diff line
@@ -16,8 +16,12 @@

package com.android.settings.sound;


import static android.media.AudioManager.STREAM_DEVICES_CHANGED_ACTION;
import static android.media.AudioManager.STREAM_MUSIC;
import static android.media.AudioManager.STREAM_VOICE_CALL;
import static android.media.AudioSystem.DEVICE_OUT_ALL_A2DP;
import static android.media.AudioSystem.DEVICE_OUT_ALL_SCO;
import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID;
import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;

import android.bluetooth.BluetoothDevice;
@@ -38,19 +42,22 @@ import androidx.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.FeatureFlagUtils;

import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.FeatureFlags;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.HeadsetProfile;
import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;

import java.util.ArrayList;
import java.util.List;

/**
@@ -65,12 +72,12 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont

    private static final int INVALID_INDEX = -1;

    protected final List<BluetoothDevice> mConnectedDevices;
    protected final AudioManager mAudioManager;
    protected final MediaRouter mMediaRouter;
    protected final LocalBluetoothProfileManager mProfileManager;
    protected int mSelectedIndex;
    protected Preference mPreference;
    protected List<BluetoothDevice> mConnectedDevices;

    private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback;
    private final LocalBluetoothManager mLocalBluetoothManager;
@@ -89,6 +96,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
        mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback();
        mReceiver = new WiredHeadsetBroadcastReceiver();
        mMediaRouterCallback = new MediaRouterCallback();
        mConnectedDevices = new ArrayList<>();
    }

    /**
@@ -195,12 +203,105 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
    }

    protected boolean isStreamFromOutputDevice(int streamType, int device) {
        return mAudioManager.getDevicesForStream(streamType) == device;
        return (device & mAudioManager.getDevicesForStream(streamType)) != 0;
    }

    /**
     * get hands free profile(HFP) connected device
     */
    protected List<BluetoothDevice> getConnectedHfpDevices() {
        final List<BluetoothDevice> connectedDevices = new ArrayList<>();
        final HeadsetProfile hfpProfile = mProfileManager.getHeadsetProfile();
        if (hfpProfile == null) {
            return connectedDevices;
        }
        final List<BluetoothDevice> devices = hfpProfile.getConnectedDevices();
        for (BluetoothDevice device : devices) {
            if (device.isConnected()) {
                connectedDevices.add(device);
            }
        }
        return connectedDevices;
    }

    /**
     * get A2dp connected device
     */
    protected List<BluetoothDevice> getConnectedA2dpDevices() {
        final List<BluetoothDevice> connectedDevices = new ArrayList<>();
        final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
        if (a2dpProfile == null) {
            return connectedDevices;
        }
        final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
        for (BluetoothDevice device : devices) {
            if (device.isConnected()) {
                connectedDevices.add(device);
            }
        }
        return connectedDevices;
    }

    /**
     * get hearing aid profile connected device, exclude other devices with same hiSyncId.
     */
    protected List<BluetoothDevice> getConnectedHearingAidDevices() {
        final List<BluetoothDevice> connectedDevices = new ArrayList<>();
        final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
        if (hapProfile == null) {
            return connectedDevices;
        }
        final List<Long> devicesHiSyncIds = new ArrayList<>();
        final List<BluetoothDevice> devices = hapProfile.getConnectedDevices();
        for (BluetoothDevice device : devices) {
            final long hiSyncId = hapProfile.getHiSyncId(device);
            // device with same hiSyncId should not be shown in the UI.
            // So do not add it into connectedDevices.
            if (!devicesHiSyncIds.contains(hiSyncId) && device.isConnected()) {
                devicesHiSyncIds.add(hiSyncId);
                connectedDevices.add(device);
            }
        }
        return connectedDevices;
    }

    /**
     * According to different stream and output device, find the active device from
     * the corresponding profile. Hearing aid device could stream both STREAM_MUSIC
     * and STREAM_VOICE_CALL.
     *
     * @param streamType the type of audio streams.
     * @return the active device. Return null if the active device is current device
     * or streamType is not STREAM_MUSIC or STREAM_VOICE_CALL.
     */
    protected BluetoothDevice findActiveDevice(int streamType) {
        if (streamType != STREAM_MUSIC && streamType != STREAM_VOICE_CALL) {
            return null;
        }
        if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_ALL_A2DP)) {
            return mProfileManager.getA2dpProfile().getActiveDevice();
        } else if (isStreamFromOutputDevice(STREAM_VOICE_CALL, DEVICE_OUT_ALL_SCO)) {
            return mProfileManager.getHeadsetProfile().getActiveDevice();
        } else if (isStreamFromOutputDevice(streamType, DEVICE_OUT_HEARING_AID)) {
            // The first element is the left active device; the second element is
            // the right active device. And they will have same hiSyncId. If either
            // or both side is not active, it will be null on that position.
            List<BluetoothDevice> activeDevices =
                    mProfileManager.getHearingAidProfile().getActiveDevices();
            for (BluetoothDevice btDevice : activeDevices) {
                if (btDevice != null && mConnectedDevices.contains(btDevice)) {
                    // also need to check mConnectedDevices, because one of
                    // the device(same hiSyncId) might not be shown in the UI.
                    return btDevice;
                }
            }
        }
        return null;
    }

    int getDefaultDeviceIndex() {
        // Default device is after all connected devices.
        return ArrayUtils.size(mConnectedDevices);
        return mConnectedDevices.size();
    }

    void setupPreferenceEntries(CharSequence[] mediaOutputs, CharSequence[] mediaValues,
@@ -261,7 +362,7 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
        mContext.unregisterReceiver(mReceiver);
    }

    /** Callback for headset plugged and unplugged events. */
    /** Notifications of audio device connection and disconnection events. */
    private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback {
        @Override
        public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
+23 −14
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.settings.sound;

import static android.bluetooth.IBluetoothHearingAid.HI_SYNC_ID_INVALID;
import static android.media.AudioManager.STREAM_VOICE_CALL;
import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET;

@@ -25,12 +26,12 @@ import android.bluetooth.BluetoothDevice;
import android.content.Context;
import androidx.preference.Preference;

import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settingslib.bluetooth.HeadsetProfile;
import com.android.settingslib.bluetooth.HearingAidProfile;

/**
 * This class allows switching between HFP-connected BT devices
 * This class allows switching between HFP-connected & HAP-connected BT devices
 * while in on-call state.
 */
public class HandsFreeProfileOutputPreferenceController extends
@@ -57,16 +58,11 @@ public class HandsFreeProfileOutputPreferenceController extends
        // Ongoing call status, list all the connected devices support hands free profile.
        // Select current active device.
        // Disable switch entry if there is no connected device.
        mConnectedDevices = null;
        BluetoothDevice activeDevice = null;
        mConnectedDevices.clear();
        mConnectedDevices.addAll(getConnectedHfpDevices());
        mConnectedDevices.addAll(getConnectedHearingAidDevices());

        final HeadsetProfile headsetProfile = mProfileManager.getHeadsetProfile();
        if (headsetProfile != null) {
            mConnectedDevices = headsetProfile.getConnectedDevices();
            activeDevice = headsetProfile.getActiveDevice();
        }

        final int numDevices = ArrayUtils.size(mConnectedDevices);
        final int numDevices = mConnectedDevices.size();
        if (numDevices == 0) {
            // No connected devices, disable switch entry.
            mPreference.setVisible(false);
@@ -79,7 +75,7 @@ public class HandsFreeProfileOutputPreferenceController extends
        CharSequence[] mediaValues = new CharSequence[numDevices + 1];

        // Setup devices entries, select active connected device
        setupPreferenceEntries(mediaOutputs, mediaValues, activeDevice);
        setupPreferenceEntries(mediaOutputs, mediaValues, findActiveDevice(STREAM_VOICE_CALL));

        if (isStreamFromOutputDevice(STREAM_VOICE_CALL, DEVICE_OUT_USB_HEADSET)) {
            // If wired headset is plugged in and active, select to default device.
@@ -92,8 +88,21 @@ public class HandsFreeProfileOutputPreferenceController extends

    @Override
    public void setActiveBluetoothDevice(BluetoothDevice device) {
        if (Utils.isAudioModeOngoingCall(mContext)) {
            mProfileManager.getHeadsetProfile().setActiveDevice(device);
        if (!Utils.isAudioModeOngoingCall(mContext)) {
            return;
        }
        final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
        final HeadsetProfile hfpProfile = mProfileManager.getHeadsetProfile();
        if (hapProfile != null && hfpProfile != null && device == null) {
            hfpProfile.setActiveDevice(null);
            hapProfile.setActiveDevice(null);
            return;
        }
        if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) {
            hapProfile.setActiveDevice(device);
        }
        if (hfpProfile != null) {
            hfpProfile.setActiveDevice(device);
        }
    }
}
+23 −14
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.settings.sound;

import static android.bluetooth.IBluetoothHearingAid.HI_SYNC_ID_INVALID;
import static android.media.AudioManager.STREAM_MUSIC;
import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET;
@@ -27,13 +28,12 @@ import android.content.Context;
import android.media.AudioManager;
import androidx.preference.Preference;

import com.android.internal.util.ArrayUtils;
import com.android.settings.R;
import com.android.settingslib.bluetooth.A2dpProfile;

import com.android.settingslib.bluetooth.HearingAidProfile;

/**
 * This class which allows switching between a2dp-connected BT devices.
 * This class which allows switching between A2dp-connected & HAP-connected BT devices.
 * A few conditions will disable this switcher:
 * - No available BT device(s)
 * - Media stream captured by cast device
@@ -67,18 +67,14 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro
            return;
        }

        mConnectedDevices.clear();
        // Otherwise, list all of the A2DP connected device and display the active device.
        mConnectedDevices = null;
        BluetoothDevice activeDevice = null;
        if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) {
            final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
            if (a2dpProfile != null) {
                mConnectedDevices = a2dpProfile.getConnectedDevices();
                activeDevice = a2dpProfile.getActiveDevice();
            }
            mConnectedDevices.addAll(getConnectedA2dpDevices());
            mConnectedDevices.addAll(getConnectedHearingAidDevices());
        }

        final int numDevices = ArrayUtils.size(mConnectedDevices);
        final int numDevices = mConnectedDevices.size();
        if (numDevices == 0) {
            // Disable switch entry if there is no connected devices.
            mPreference.setVisible(false);
@@ -91,7 +87,7 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro
        CharSequence[] mediaValues = new CharSequence[numDevices + 1];

        // Setup devices entries, select active connected device
        setupPreferenceEntries(mediaOutputs, mediaValues, activeDevice);
        setupPreferenceEntries(mediaOutputs, mediaValues, findActiveDevice(STREAM_MUSIC));

        if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_USB_HEADSET)) {
            // If wired headset is plugged in and active, select to default device.
@@ -104,8 +100,21 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro

    @Override
    public void setActiveBluetoothDevice(BluetoothDevice device) {
        if (mAudioManager.getMode() == AudioManager.MODE_NORMAL) {
            mProfileManager.getA2dpProfile().setActiveDevice(device);
        if (mAudioManager.getMode() != AudioManager.MODE_NORMAL) {
            return;
        }
        final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
        final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
        if (hapProfile != null && a2dpProfile != null && device == null) {
            hapProfile.setActiveDevice(null);
            a2dpProfile.setActiveDevice(null);
            return;
        }
        if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) {
            hapProfile.setActiveDevice(device);
        }
        if (a2dpProfile != null) {
            a2dpProfile.setActiveDevice(device);
        }
    }
}
+297 −23

File changed.

Preview size limit exceeded, changes collapsed.

+258 −34

File changed.

Preview size limit exceeded, changes collapsed.

Loading