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

Commit d7c9598a authored by Aniket Kumar Lata's avatar Aniket Kumar Lata Committed by Jean-Michel Trivi
Browse files

audio: Restructure A2DP active device change

Make active device change asynchronous.
Restructure A2DP active device change API
for clarity and speed.
Merge active device and device config change
handlers.
Fix bug for a new A2DP device connection with
handleBluetoothA2dpActiveDeviceChange.

Bug: 122944517
Test: still needs Bt side using new interface
Change-Id: Ia2fa6b2c98ed4452880e8abca4a069b904f8cc68
parent 75f61c59
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -4144,6 +4144,10 @@ public class AudioManager {
     /**
     * Indicate A2DP source or sink active device change and eventually suppress
     * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
     * This operation is asynchronous but its execution will still be sequentially scheduled
     * relative to calls to {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice,
     * int, boolean, int)} and
     * {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}.
     * @param device Bluetooth device connected/disconnected
     * @param state  new connection state (BluetoothProfile.STATE_xxx)
     * @param profile profile for the A2DP device
@@ -4157,18 +4161,16 @@ public class AudioManager {
     * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent.
     * {@hide}
     */
    public int handleBluetoothA2dpActiveDeviceChange(
    public void handleBluetoothA2dpActiveDeviceChange(
                BluetoothDevice device, int state, int profile,
                boolean suppressNoisyIntent, int a2dpVolume) {
        final IAudioService service = getService();
        int delay = 0;
        try {
            delay = service.handleBluetoothA2dpActiveDeviceChange(device,
            service.handleBluetoothA2dpActiveDeviceChange(device,
                state, profile, suppressNoisyIntent, a2dpVolume);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        return delay;
    }

    /** {@hide} */
+1 −1
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ interface IAudioService {

    void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device);

    int handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device,
    void handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device,
            int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);

    @UnsupportedAppUsage
+30 −12
Original line number Diff line number Diff line
@@ -230,17 +230,13 @@ import java.util.ArrayList;
        sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
    }

    /*package*/ int handleBluetoothA2dpActiveDeviceChange(
    /*package*/ void postBluetoothA2dpDeviceConfigChangeExt(
            @NonNull BluetoothDevice device,
            @AudioService.BtProfileConnectionState int state, int profile,
            boolean suppressNoisyIntent, int a2dpVolume) {
        // FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
        //   of handleBluetoothA2dpDeviceConfigChange and
        //   setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
        synchronized (mDeviceStateLock) {
            return mDeviceInventory.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
        final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
                suppressNoisyIntent, a2dpVolume);
        }
        sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE, info);
    }

    private static final class HearingAidDeviceConnectionInfo {
@@ -542,7 +538,8 @@ import java.util.ArrayList;
        mBrokerHandler.removeMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
    }

    /*package*/ void postA2dpActiveDeviceChange(BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
    /*package*/ void postA2dpActiveDeviceChange(
                    @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
        sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo);
    }

@@ -714,8 +711,9 @@ import java.util.ArrayList;
                    final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
                    synchronized (mDeviceStateLock) {
                        a2dpCodec = mBtHelper.getA2dpCodec(btDevice);
                        mDeviceInventory.onBluetoothA2dpDeviceConfigChange(
                                new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec));
                        mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
                                new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec),
                                        BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
                    }
                    break;
                case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
@@ -744,7 +742,8 @@ import java.util.ArrayList;
                case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
                    synchronized (mDeviceStateLock) {
                        mDeviceInventory.onBluetoothA2dpActiveDeviceChange(
                                (BtHelper.BluetoothA2dpDeviceInfo) msg.obj);
                                (BtHelper.BluetoothA2dpDeviceInfo) msg.obj,
                                 BtHelper.EVENT_ACTIVE_DEVICE_CHANGE);
                    }
                    break;
                case MSG_DISCONNECT_A2DP:
@@ -816,6 +815,22 @@ import java.util.ArrayList;
                                info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice);
                    }
                } break;
                case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT: {
                    final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
                    AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
                            "handleBluetoothA2dpActiveDeviceChangeExt "
                                    + " state=" + info.mState
                                    // only querying address as this is the only readily available
                                    // field on the device
                                    + " addr=" + info.mDevice.getAddress()
                                    + " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy
                                    + " vol=" + info.mVolume)).printLog(TAG));
                    synchronized (mDeviceStateLock) {
                        mDeviceInventory.handleBluetoothA2dpActiveDeviceChangeExt(
                                info.mDevice, info.mState, info.mProfile,
                                info.mSupprNoisy, info.mVolume);
                    }
                } break;
                default:
                    Log.wtf(TAG, "Invalid message " + msg.what);
            }
@@ -863,6 +878,8 @@ import java.util.ArrayList;
    private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27;
    // process external command to (dis)connect a hearing aid device
    private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28;
    // process external command to (dis)connect or change active A2DP device
    private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT = 29;


    private static boolean isMessageHandledUnderWakelock(int msgId) {
@@ -877,6 +894,7 @@ import java.util.ArrayList;
            case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
            case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
            case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT:
                return true;
            default:
                return false;
+59 −104
Original line number Diff line number Diff line
@@ -263,74 +263,25 @@ public final class AudioDeviceInventory {
        }
    }

    /*package*/ void onBluetoothA2dpDeviceConfigChange(
            @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo) {
    /*package*/ void onBluetoothA2dpActiveDeviceChange(
            @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
        final BluetoothDevice btDevice = btInfo.getBtDevice();
        if (AudioService.DEBUG_DEVICES) {
            Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice);
        }
        if (btDevice == null) {
            return;
        }
        String address = btDevice.getAddress();
        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
            address = "";
        }
        AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
                "onBluetoothA2dpDeviceConfigChange addr=" + address));

        final int a2dpCodec = btInfo.getCodec();

        synchronized (mConnectedDevices) {
            if (mDeviceBroker.hasScheduledA2dpSinkConnectionState(btDevice)) {
                AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
                        "A2dp config change ignored"));
                return;
            }
            final String key =
                    DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
            final DeviceInfo di = mConnectedDevices.get(key);
            if (di == null) {
                Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpDeviceConfigChange");
                return;
            }
            // Device is connected
            if (di.mDeviceCodecFormat != a2dpCodec) {
                di.mDeviceCodecFormat = a2dpCodec;
                mConnectedDevices.replace(key, di);
            }
        if (AudioService.DEBUG_DEVICES) {
                Log.d(TAG, "onBluetoothA2dpDeviceConfigChange: codec="
                        + di.mDeviceCodecFormat);
            }
            if (AudioSystem.handleDeviceConfigChange(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
                    btDevice.getName(), di.mDeviceCodecFormat) != AudioSystem.AUDIO_STATUS_OK) {
                // force A2DP device disconnection in case of error so that AudioService state
                // is consistent with audio policy manager state
                final int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
                setBluetoothA2dpDeviceConnectionState(
                        btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
                        false /* suppressNoisyIntent */, musicDevice,
                        -1 /* a2dpVolume */);
            }
        }
            Log.d(TAG, "onBluetoothA2dpActiveDeviceChange btDevice=" + btDevice);
        }

    /*package*/ void onBluetoothA2dpActiveDeviceChange(
            @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo) {
        final BluetoothDevice btDevice = btInfo.getBtDevice();
        int a2dpVolume = btInfo.getVolume();
        final int a2dpCodec = btInfo.getCodec();

        if (AudioService.DEBUG_DEVICES) {
            Log.d(TAG, "onBluetoothA2dpActiveDeviceChange btDevice=" + btDevice);
        }
        String address = btDevice.getAddress();
        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
            address = "";
        }
        AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
                "onBluetoothA2dpActiveDeviceChange addr=" + address));
                "onBluetoothA2dpActiveDeviceChange addr=" + address
                    + " event=" + BtHelper.a2dpDeviceEventToString(event)));

        synchronized (mConnectedDevices) {
            //TODO original CL is not consistent between BluetoothDevice and BluetoothA2dpDeviceInfo
@@ -344,9 +295,11 @@ public final class AudioDeviceInventory {
                    AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
            final DeviceInfo di = mConnectedDevices.get(key);
            if (di == null) {
                Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpActiveDeviceChange");
                return;
            }

            if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) {
                // Device is connected
                if (a2dpVolume != -1) {
                    final AudioService.VolumeStreamState streamState =
@@ -355,9 +308,15 @@ public final class AudioDeviceInventory {
                    a2dpVolume = a2dpVolume * 10;
                    streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                            "onBluetoothA2dpActiveDeviceChange");
                mDeviceBroker.setDeviceVolume(streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
                    mDeviceBroker.setDeviceVolume(
                            streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
                }
            } else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
                if (di.mDeviceCodecFormat != a2dpCodec) {
                    di.mDeviceCodecFormat = a2dpCodec;
                    mConnectedDevices.replace(key, di);
                }
            }

            if (AudioSystem.handleDeviceConfigChange(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
                    btDevice.getName(), a2dpCodec) != AudioSystem.AUDIO_STATUS_OK) {
                int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
@@ -616,52 +575,48 @@ public final class AudioDeviceInventory {
        }
    }

    /*package*/ int handleBluetoothA2dpActiveDeviceChange(
    /*package*/ void handleBluetoothA2dpActiveDeviceChangeExt(
            @NonNull BluetoothDevice device,
            @AudioService.BtProfileConnectionState int state, int profile,
            boolean suppressNoisyIntent, int a2dpVolume) {
        // method was added by QC but never used, and now conflicts with async behavior of
        // handleBluetoothA2dpDeviceConfigChange and
        // setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
        if (false) {
        if (state == BluetoothProfile.STATE_DISCONNECTED) {
                setBluetoothA2dpDeviceConnectionState(device, state, profile,
                        suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume);
            mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
                           device, state, profile, suppressNoisyIntent, a2dpVolume);
            return;
        }
        // state == BluetoothProfile.STATE_CONNECTED
        synchronized (mConnectedDevices) {
            final String address = device.getAddress();
            final int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
            final String deviceKey = DeviceInfo.makeDeviceListKey(
                        AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
            DeviceInfo deviceInfo = mConnectedDevices.get(deviceKey);
            if (deviceInfo != null) {
                // Device config change for matching A2DP device
                mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
                return;
            }
            for (int i = 0; i < mConnectedDevices.size(); i++) {
                    final DeviceInfo deviceInfo = mConnectedDevices.valueAt(i);
                deviceInfo = mConnectedDevices.valueAt(i);
                if (deviceInfo.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
                    continue;
                }
                    // If A2DP device exists, this is either an active device change or
                    // device config change
                // A2DP device exists, handle active device change
                final String existingDevicekey = mConnectedDevices.keyAt(i);
                final String deviceName = device.getName();
                    final String address = device.getAddress();
                    final String newDeviceKey = DeviceInfo.makeDeviceListKey(
                            AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
                    int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
                    // Device not equal to existing device, active device change
                    if (!TextUtils.equals(existingDevicekey, newDeviceKey)) {
                mConnectedDevices.remove(existingDevicekey);
                        mConnectedDevices.put(newDeviceKey, new DeviceInfo(
                mConnectedDevices.put(deviceKey, new DeviceInfo(
                        AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName,
                        address, a2dpCodec));
                mDeviceBroker.postA2dpActiveDeviceChange(
                        new BtHelper.BluetoothA2dpDeviceInfo(
                            device, a2dpVolume, a2dpCodec));
                        return 0;
                    } else {
                        // Device config change for existing device
                        mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
                        return 0;
                    }
                }
                return;
            }
        }
        return 0;
        // New A2DP device connection
        mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
                           device, state, profile, suppressNoisyIntent, a2dpVolume);
    }

    /*package*/ int setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state,
+2 −5
Original line number Diff line number Diff line
@@ -4094,12 +4094,9 @@ public class AudioService extends IAudioService.Stub
     * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int,
     *                                                          boolean, int)
     */
    public int handleBluetoothA2dpActiveDeviceChange(
    public void handleBluetoothA2dpActiveDeviceChange(
            BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
            int a2dpVolume) {
        // FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
        //   of handleBluetoothA2dpDeviceConfigChange and
        //   setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
        if (device == null) {
            throw new IllegalArgumentException("Illegal null device");
        }
@@ -4110,7 +4107,7 @@ public class AudioService extends IAudioService.Stub
                && state != BluetoothProfile.STATE_DISCONNECTED) {
            throw new IllegalArgumentException("Invalid state " + state);
        }
        return mDeviceBroker.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
        mDeviceBroker.postBluetoothA2dpDeviceConfigChangeExt(device, state, profile,
                suppressNoisyIntent, a2dpVolume);
    }

Loading