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

Commit 84d04040 authored by Eric Laurent's avatar Eric Laurent Committed by Automerger Merge Worker
Browse files

Merge "AudioService: BT dual mode support" into udc-dev am: b44e8313

parents cf7f96cd b44e8313
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
@@ -1237,6 +1237,9 @@ public class AudioSystem
    public static final Set<Integer> DEVICE_IN_ALL_SCO_SET;
    /** @hide */
    public static final Set<Integer> DEVICE_IN_ALL_USB_SET;
    /** @hide */
    public static final Set<Integer> DEVICE_IN_ALL_BLE_SET;

    static {
        DEVICE_IN_ALL_SET = new HashSet<>();
        DEVICE_IN_ALL_SET.add(DEVICE_IN_COMMUNICATION);
@@ -1276,6 +1279,66 @@ public class AudioSystem
        DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_ACCESSORY);
        DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_DEVICE);
        DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_HEADSET);

        DEVICE_IN_ALL_BLE_SET = new HashSet<>();
        DEVICE_IN_ALL_BLE_SET.add(DEVICE_IN_BLE_HEADSET);
    }

    /** @hide */
    public static boolean isBluetoothDevice(int deviceType) {
        return isBluetoothA2dpOutDevice(deviceType)
                || isBluetoothScoDevice(deviceType)
                || isBluetoothLeDevice(deviceType);
    }

    /** @hide */
    public static boolean isBluetoothOutDevice(int deviceType) {
        return isBluetoothA2dpOutDevice(deviceType)
                || isBluetoothScoOutDevice(deviceType)
                || isBluetoothLeOutDevice(deviceType);
    }

    /** @hide */
    public static boolean isBluetoothInDevice(int deviceType) {
        return isBluetoothScoInDevice(deviceType)
                || isBluetoothLeInDevice(deviceType);
    }

    /** @hide */
    public static boolean isBluetoothA2dpOutDevice(int deviceType) {
        return DEVICE_OUT_ALL_A2DP_SET.contains(deviceType);
    }

    /** @hide */
    public static boolean isBluetoothScoOutDevice(int deviceType) {
        return DEVICE_OUT_ALL_SCO_SET.contains(deviceType);
    }

    /** @hide */
    public static boolean isBluetoothScoInDevice(int deviceType) {
        return DEVICE_IN_ALL_SCO_SET.contains(deviceType);
    }

    /** @hide */
    public static boolean isBluetoothScoDevice(int deviceType) {
        return isBluetoothScoOutDevice(deviceType)
                || isBluetoothScoInDevice(deviceType);
    }

    /** @hide */
    public static boolean isBluetoothLeOutDevice(int deviceType) {
        return DEVICE_OUT_ALL_BLE_SET.contains(deviceType);
    }

    /** @hide */
    public static boolean isBluetoothLeInDevice(int deviceType) {
        return DEVICE_IN_ALL_BLE_SET.contains(deviceType);
    }

    /** @hide */
    public static boolean isBluetoothLeDevice(int deviceType) {
        return isBluetoothLeOutDevice(deviceType)
                || isBluetoothLeInDevice(deviceType);
    }

    /** @hide */
+43 −19
Original line number Diff line number Diff line
@@ -88,14 +88,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
    private final @NonNull AudioSystemAdapter mAudioSystem;

    /** ID for Communication strategy retrieved form audio policy manager */
    private int mCommunicationStrategyId = -1;
    /*package*/  int mCommunicationStrategyId = -1;

    /** ID for Accessibility strategy retrieved form audio policy manager */
    private int mAccessibilityStrategyId = -1;


    /** Active communication device reported by audio policy manager */
    private AudioDeviceInfo mActiveCommunicationDevice;
    /*package*/ AudioDeviceInfo mActiveCommunicationDevice;
    /** Last preferred device set for communication strategy */
    private AudioDeviceAttributes mPreferredCommunicationDevice;

@@ -755,6 +755,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
            mIsLeOutput = false;
        }

        BtDeviceInfo(@NonNull BtDeviceInfo src, int state) {
            mDevice = src.mDevice;
            mState = state;
            mProfile = src.mProfile;
            mSupprNoisy = src.mSupprNoisy;
            mVolume = src.mVolume;
            mIsLeOutput = src.mIsLeOutput;
            mEventSource = src.mEventSource;
            mAudioSystemDevice = src.mAudioSystemDevice;
            mMusicDevice = src.mMusicDevice;
            mCodec = src.mCodec;
        }

        // redefine equality op so we can match messages intended for this device
        @Override
        public boolean equals(Object o) {
@@ -821,7 +834,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
     * @param info struct with the (dis)connection information
     */
    /*package*/ void queueOnBluetoothActiveDeviceChanged(@NonNull BtDeviceChangedData data) {
        if (data.mInfo.getProfile() == BluetoothProfile.A2DP && data.mPreviousDevice != null
        if (data.mPreviousDevice != null
                && data.mPreviousDevice.equals(data.mNewDevice)) {
            final String name = TextUtils.emptyIfNull(data.mNewDevice.getName());
            new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR
@@ -830,7 +843,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
                    .set(MediaMetrics.Property.STATUS, data.mInfo.getProfile())
                    .record();
            synchronized (mDeviceStateLock) {
                postBluetoothA2dpDeviceConfigChange(data.mNewDevice);
                postBluetoothDeviceConfigChange(createBtDeviceInfo(data, data.mNewDevice,
                        BluetoothProfile.STATE_CONNECTED));
            }
        } else {
            synchronized (mDeviceStateLock) {
@@ -1064,8 +1078,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
                new AudioModeInfo(mode, pid, uid));
    }

    /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) {
        sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device);
    /*package*/ void postBluetoothDeviceConfigChange(@NonNull BtDeviceInfo info) {
        sendLMsgNoDelay(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, info);
    }

    /*package*/ void startBluetoothScoForClient(IBinder cb, int pid, int scoAudioMode,
@@ -1322,6 +1336,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
        sendIMsgNoDelay(MSG_I_SCO_AUDIO_STATE_CHANGED, SENDMSG_QUEUE, state);
    }

    /*package*/ void postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice) {
        sendLMsgNoDelay(MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED, SENDMSG_QUEUE, btDevice);
    }

    /*package*/ static final class CommunicationDeviceInfo {
        final @NonNull IBinder mCb; // Identifies the requesting client for death handler
        final int mPid; // Requester process ID
@@ -1397,9 +1415,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
        }
    }

    /*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect) {
    /*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes,
                                boolean connect, @Nullable BluetoothDevice btDevice) {
        synchronized (mDeviceStateLock) {
            return mDeviceInventory.handleDeviceConnection(attributes, connect, false /*for test*/);
            return mDeviceInventory.handleDeviceConnection(
                    attributes, connect, false /*for test*/, btDevice);
        }
    }

@@ -1640,13 +1660,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
                                (String) msg.obj, msg.arg1);
                    }
                    break;
                case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
                    final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
                case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
                    synchronized (mDeviceStateLock) {
                        final int a2dpCodec = mBtHelper.getA2dpCodec(btDevice);
                        mDeviceInventory.onBluetoothA2dpDeviceConfigChange(
                                new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec),
                                        BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
                        mDeviceInventory.onBluetoothDeviceConfigChange(
                                (BtDeviceInfo) msg.obj, BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
                    }
                    break;
                case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
@@ -1810,6 +1827,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
                case MSG_IL_SET_LEAUDIO_SUSPENDED: {
                    setLeAudioSuspended((msg.arg1 == 1), false /*internal*/, (String) msg.obj);
                } break;
                case MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED: {
                    final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
                    BtHelper.onNotifyPreferredAudioProfileApplied(btDevice);
                } break;
                default:
                    Log.wtf(TAG, "Invalid message " + msg.what);
            }
@@ -1845,7 +1866,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
    private static final int MSG_IL_BTA2DP_TIMEOUT = 10;

    // process change of A2DP device configuration, obj is BluetoothDevice
    private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11;
    private static final int MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE = 11;

    private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12;
    private static final int MSG_REPORT_NEW_ROUTES = 13;
@@ -1887,13 +1908,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
    private static final int MSG_IL_SET_A2DP_SUSPENDED = 50;
    private static final int MSG_IL_SET_LEAUDIO_SUSPENDED = 51;

    private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 52;

    private static boolean isMessageHandledUnderWakelock(int msgId) {
        switch(msgId) {
            case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
            case MSG_L_SET_BT_ACTIVE_DEVICE:
            case MSG_IL_BTA2DP_TIMEOUT:
            case MSG_IL_BTLEAUDIO_TIMEOUT:
            case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
            case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
            case MSG_TOGGLE_HDMI:
            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
            case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
@@ -1985,7 +2008,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
                case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
                case MSG_IL_BTA2DP_TIMEOUT:
                case MSG_IL_BTLEAUDIO_TIMEOUT:
                case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
                case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
                    if (sLastDeviceConnectMsgTime >= time) {
                        // add a little delay to make sure messages are ordered as expected
                        time = sLastDeviceConnectMsgTime + 30;
@@ -2005,7 +2028,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
    static {
        MESSAGES_MUTE_MUSIC = new HashSet<>();
        MESSAGES_MUTE_MUSIC.add(MSG_L_SET_BT_ACTIVE_DEVICE);
        MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE);
        MESSAGES_MUTE_MUSIC.add(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE);
        MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT);
        MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE);
    }
@@ -2026,7 +2049,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
        // Do not mute on bluetooth event if music is playing on a wired headset.
        if ((message == MSG_L_SET_BT_ACTIVE_DEVICE
                || message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT
                || message == MSG_L_A2DP_DEVICE_CONFIG_CHANGE)
                || message == MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE)
                && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
                && hasIntersection(mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET,
                        mAudioService.getDeviceSetForStream(AudioSystem.STREAM_MUSIC))) {
@@ -2173,6 +2196,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
                mDeviceInventory.removePreferredDevicesForStrategy(mCommunicationStrategyId);
                mDeviceInventory.removePreferredDevicesForStrategy(mAccessibilityStrategyId);
            }
            mDeviceInventory.applyConnectedDevicesRoles();
        } else {
            mDeviceInventory.setPreferredDevicesForStrategy(
                    mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice));
+372 −105

File changed.

Preview size limit exceeded, changes collapsed.

+34 −59
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.BluetoothProfileConnectionInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -150,60 +151,12 @@ public class BtHelper {
        }
    }

    //----------------------------------------------------------------------
    /*package*/ static class BluetoothA2dpDeviceInfo {
        private final @NonNull BluetoothDevice mBtDevice;
        private final int mVolume;
        private final @AudioSystem.AudioFormatNativeEnumForBtCodec int mCodec;

        BluetoothA2dpDeviceInfo(@NonNull BluetoothDevice btDevice) {
            this(btDevice, -1, AudioSystem.AUDIO_FORMAT_DEFAULT);
        }

        BluetoothA2dpDeviceInfo(@NonNull BluetoothDevice btDevice, int volume, int codec) {
            mBtDevice = btDevice;
            mVolume = volume;
            mCodec = codec;
        }

        public @NonNull BluetoothDevice getBtDevice() {
            return mBtDevice;
        }

        public int getVolume() {
            return mVolume;
        }

        public @AudioSystem.AudioFormatNativeEnumForBtCodec int getCodec() {
            return mCodec;
        }

        // redefine equality op so we can match messages intended for this device
        @Override
        public boolean equals(Object o) {
            if (o == null) {
                return false;
            }
            if (this == o) {
                return true;
            }
            if (o instanceof BluetoothA2dpDeviceInfo) {
                return mBtDevice.equals(((BluetoothA2dpDeviceInfo) o).getBtDevice());
            }
            return false;
        }


    }

    // A2DP device events
    /*package*/ static final int EVENT_DEVICE_CONFIG_CHANGE = 0;
    /*package*/ static final int EVENT_ACTIVE_DEVICE_CHANGE = 1;

    /*package*/ static String a2dpDeviceEventToString(int event) {
    /*package*/ static String deviceEventToString(int event) {
        switch (event) {
            case EVENT_DEVICE_CONFIG_CHANGE: return "DEVICE_CONFIG_CHANGE";
            case EVENT_ACTIVE_DEVICE_CHANGE: return "ACTIVE_DEVICE_CHANGE";
            default:
                return new String("invalid event:" + event);
        }
@@ -620,11 +573,12 @@ public class BtHelper {
        return btHeadsetDeviceToAudioDevice(mBluetoothHeadsetDevice);
    }

    private AudioDeviceAttributes btHeadsetDeviceToAudioDevice(BluetoothDevice btDevice) {
    private static AudioDeviceAttributes btHeadsetDeviceToAudioDevice(BluetoothDevice btDevice) {
        if (btDevice == null) {
            return new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, "");
        }
        String address = btDevice.getAddress();
        String name = getName(btDevice);
        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
            address = "";
        }
@@ -646,7 +600,7 @@ public class BtHelper {
                    + " btClass: " + (btClass == null ? "Unknown" : btClass)
                    + " nativeType: " + nativeType + " address: " + address);
        }
        return new AudioDeviceAttributes(nativeType, address);
        return new AudioDeviceAttributes(nativeType, address, name);
    }

    private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
@@ -655,12 +609,9 @@ public class BtHelper {
        }
        int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
        AudioDeviceAttributes audioDevice =  btHeadsetDeviceToAudioDevice(btDevice);
        String btDeviceName =  getName(btDevice);
        boolean result = false;
        if (isActive) {
            result |= mDeviceBroker.handleDeviceConnection(new AudioDeviceAttributes(
                    audioDevice.getInternalType(), audioDevice.getAddress(), btDeviceName),
                    isActive);
            result |= mDeviceBroker.handleDeviceConnection(audioDevice, isActive, btDevice);
        } else {
            int[] outDeviceTypes = {
                    AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
@@ -669,14 +620,14 @@ public class BtHelper {
            };
            for (int outDeviceType : outDeviceTypes) {
                result |= mDeviceBroker.handleDeviceConnection(new AudioDeviceAttributes(
                        outDeviceType, audioDevice.getAddress(), btDeviceName),
                        isActive);
                        outDeviceType, audioDevice.getAddress(), audioDevice.getName()),
                        isActive, btDevice);
            }
        }
        // handleDeviceConnection() && result to make sure the method get executed
        result = mDeviceBroker.handleDeviceConnection(new AudioDeviceAttributes(
                        inDevice, audioDevice.getAddress(), btDeviceName),
                isActive) && result;
                        inDevice, audioDevice.getAddress(), audioDevice.getName()),
                isActive, btDevice) && result;
        return result;
    }

@@ -973,6 +924,30 @@ public class BtHelper {
        }
    }

    /*package */ static int getProfileFromType(int deviceType) {
        if (AudioSystem.isBluetoothA2dpOutDevice(deviceType)) {
            return BluetoothProfile.A2DP;
        } else if (AudioSystem.isBluetoothScoDevice(deviceType)) {
            return BluetoothProfile.HEADSET;
        } else if (AudioSystem.isBluetoothLeDevice(deviceType)) {
            return BluetoothProfile.LE_AUDIO;
        }
        return 0; // 0 is not a valid profile
    }

    /*package */ static Bundle getPreferredAudioProfiles(String address) {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        return adapter.getPreferredAudioProfiles(adapter.getRemoteDevice(address));
    }

    /**
     * Notifies Bluetooth framework that new preferred audio profiles for Bluetooth devices
     * have been applied.
     */
    public static void onNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice) {
        BluetoothAdapter.getDefaultAdapter().notifyActiveDeviceChangeApplied(btDevice);
    }

    /**
     * Returns the string equivalent for the btDeviceClass class.
     */