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

Commit ad28e22c authored by Roopa Sattiraju's avatar Roopa Sattiraju Committed by Gerrit Code Review
Browse files

Merge "A2DP switch device refactor"

parents 4029a5bc 94610acf
Loading
Loading
Loading
Loading
+17 −21
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.BtProfileConnectionInfo;
import android.os.HandlerThread;
import android.util.Log;

@@ -462,13 +463,10 @@ public class A2dpService extends ProfileService {
            // device, the user has explicitly switched the output to the local device and music
            // should continue playing. Otherwise, the remote device has been indeed disconnected
            // and audio should be suspended before switching the output to the local device.
            boolean suppressNoisyIntent = !forceStopPlayingAudio
                    && (getConnectionState(previousActiveDevice)
                    == BluetoothProfile.STATE_CONNECTED);
            Log.i(TAG, "removeActiveDevice: suppressNoisyIntent=" + suppressNoisyIntent);
            mAudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
                    previousActiveDevice, BluetoothProfile.STATE_DISCONNECTED,
                    BluetoothProfile.A2DP, suppressNoisyIntent, -1);
            boolean stopAudio = forceStopPlayingAudio || (getConnectionState(previousActiveDevice)
                        != BluetoothProfile.STATE_CONNECTED);
            mAudioManager.handleBluetoothActiveDeviceChanged(null, previousActiveDevice,
                    BtProfileConnectionInfo.a2dpInfo(!stopAudio, -1));

            synchronized (mStateMachines) {
                // Make sure the Active device in native layer is set to null and audio is off
@@ -552,13 +550,6 @@ public class A2dpService extends ProfileService {
            // This needs to happen before we inform the audio manager that the device
            // disconnected. Please see comment in updateAndBroadcastActiveDevice() for why.
            updateAndBroadcastActiveDevice(device);
            // Make sure the Audio Manager knows the previous Active device is disconnected,
            // and the new Active device is connected.
            if (previousActiveDevice != null) {
                mAudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
                        previousActiveDevice, BluetoothProfile.STATE_DISCONNECTED,
                        BluetoothProfile.A2DP, true, -1);
            }

            BluetoothDevice newActiveDevice = null;
            synchronized (mStateMachines) {
@@ -583,13 +574,13 @@ public class A2dpService extends ProfileService {
                rememberedVolume = mFactory.getAvrcpTargetService()
                        .getRememberedVolumeForDevice(newActiveDevice);
            }
            mAudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
                    newActiveDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP,
                    true, rememberedVolume);
            // Inform the Audio Service about the codec configuration
            // Make sure the Audio Manager knows the previous Active device is disconnected,
            // and the new Active device is connected.
            // And inform the Audio Service about the codec configuration
            // change, so the Audio Service can reset accordingly the audio
            // feeding parameters in the Audio HAL to the Bluetooth stack.
            mAudioManager.handleBluetoothA2dpDeviceConfigChange(newActiveDevice);
            mAudioManager.handleBluetoothActiveDeviceChanged(newActiveDevice, previousActiveDevice,
                    BtProfileConnectionInfo.a2dpInfo(true, rememberedVolume));
        }
        return true;
    }
@@ -972,8 +963,13 @@ public class A2dpService extends ProfileService {
        // Inform the Audio Service about the codec configuration change,
        // so the Audio Service can reset accordingly the audio feeding
        // parameters in the Audio HAL to the Bluetooth stack.
        if (isActiveDevice(device) && !sameAudioFeedingParameters) {
            mAudioManager.handleBluetoothA2dpDeviceConfigChange(device);
        // Until we are able to detect from device_port_proxy if the config has changed or not,
        // the Bluetooth stack can only disable the audio session and need to ask audioManager to
        // restart the session even if feeding parameter are the same. (sameAudioFeedingParameters
        // is left unused until there)
        if (isActiveDevice(device)) {
            mAudioManager.handleBluetoothActiveDeviceChanged(device, device,
                    BtProfileConnectionInfo.a2dpInfo(false, -1));
        }
    }

+9 −23
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.BtProfileConnectionInfo;
import android.os.HandlerThread;
import android.os.ParcelUuid;
import android.util.Log;
@@ -694,31 +695,16 @@ public class HearingAidService extends ProfileService {
                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions());

        if (device == null) {
            if (DBG) {
                Log.d(TAG, "Set Hearing Aid audio to disconnected");
            }
            boolean suppressNoisyIntent =
                    (getConnectionState(mPreviousAudioDevice) == BluetoothProfile.STATE_CONNECTED);
            mAudioManager.setBluetoothHearingAidDeviceConnectionState(
                    mPreviousAudioDevice, BluetoothProfile.STATE_DISCONNECTED,
                    suppressNoisyIntent, 0);
            mPreviousAudioDevice = null;
        } else {
        boolean stopAudio = device == null
                && (getConnectionState(mPreviousAudioDevice) != BluetoothProfile.STATE_CONNECTED);
        if (DBG) {
                Log.d(TAG, "Set Hearing Aid audio to connected");
            Log.d(TAG, "Hearing Aid audio: " + mPreviousAudioDevice + " -> " + device
                    + ". Stop audio: " + stopAudio);
        }
            if (mPreviousAudioDevice != null) {
                mAudioManager.setBluetoothHearingAidDeviceConnectionState(
                        mPreviousAudioDevice, BluetoothProfile.STATE_DISCONNECTED,
                        true, 0);
            }
            mAudioManager.setBluetoothHearingAidDeviceConnectionState(
                    device, BluetoothProfile.STATE_CONNECTED,
                    true, 0);
        mAudioManager.handleBluetoothActiveDeviceChanged(device, mPreviousAudioDevice,
                BtProfileConnectionInfo.hearingAidInfo(!stopAudio));
        mPreviousAudioDevice = device;
    }
    }

    // Remove state machine if the bonding for a device is removed
    private class BondStateChangedReceiver extends BroadcastReceiver {
+58 −70
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.media.AudioManager;
import android.media.BtProfileConnectionInfo;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.ParcelUuid;
@@ -93,8 +94,8 @@ public class LeAudioService extends ProfileService {
    private AdapterService mAdapterService;
    private DatabaseManager mDatabaseManager;
    private HandlerThread mStateMachinesThread;
    private BluetoothDevice mPreviousAudioOutDevice;
    private BluetoothDevice mPreviousAudioInDevice;
    private BluetoothDevice mActiveAudioOutDevice;
    private BluetoothDevice mActiveAudioInDevice;
    ServiceFactory mServiceFactory = new ServiceFactory();

    LeAudioNativeInterface mLeAudioNativeInterface;
@@ -664,49 +665,44 @@ public class LeAudioService extends ProfileService {
        boolean newSupportedByDeviceInput = (newSupportedAudioDirections
                & AUDIO_DIRECTION_INPUT_BIT) != 0;

        if (device != null && mPreviousAudioInDevice != null) {
            int previousGroupId = getGroupId(mPreviousAudioInDevice);
        if (device != null && mActiveAudioInDevice != null) {
            int previousGroupId = getGroupId(mActiveAudioInDevice);
            if (previousGroupId == groupId) {
                /* This is thes same group as aleady notified to the system.
                * Therefore do not change the device we have connected to the group,
                * unless, previous one is disconnected now
                */
                if (mPreviousAudioInDevice.isConnected())
                    device = mPreviousAudioInDevice;
                if (mActiveAudioInDevice.isConnected()) {
                    device = mActiveAudioInDevice;
                }
            }

        /* Disconnect input:
         * - If active input device changed (to none or any)
         * - If device stops supporting input
         */
        boolean inActiveDeviceReplace = (device != mPreviousAudioInDevice);
        if (inActiveDeviceReplace && (mPreviousAudioInDevice != null)) {
            mAudioManager.setBluetoothLeAudioInDeviceConnectionState(
                    mPreviousAudioInDevice, BluetoothProfile.STATE_DISCONNECTED);
        }

        mPreviousAudioInDevice = device;
        BluetoothDevice previousInDevice = mActiveAudioInDevice;

        if (device == null) {
            Log.d(TAG,  " device is null.");
            return inActiveDeviceReplace;
        }

        if (inActiveDeviceReplace == false ||
             (oldSupportedByDeviceInput == newSupportedByDeviceInput)) {
            Log.d(TAG,  " Nothing to do.");
            return inActiveDeviceReplace;
        /*
         * Do not update input if neither previous nor current device support input
         */
        if (!oldSupportedByDeviceInput && !newSupportedByDeviceInput) {
            Log.d(TAG, "updateActiveInDevice: Device does not support input.");
            return false;
        }

        /* Connect input:
         * - If active input device changed
         * - If device starts support input
        /*
         * Update input if:
         * - Device changed
         *     OR
         * - Device stops / starts supporting input
         */
        mAudioManager.setBluetoothLeAudioInDeviceConnectionState(
                   device, BluetoothProfile.STATE_CONNECTED);

        return inActiveDeviceReplace;
        if (!Objects.equals(device, previousInDevice)
                || (oldSupportedByDeviceInput != newSupportedByDeviceInput)) {
            mActiveAudioInDevice = newSupportedByDeviceInput ? device : null;
            mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioInDevice, previousInDevice,
                    BtProfileConnectionInfo.leAudio(false, false));
            return true;
        }
        Log.d(TAG, "updateActiveInDevice: Nothing to do.");
        return false;
    }

    private boolean updateActiveOutDevice(BluetoothDevice device, Integer groupId,
@@ -722,53 +718,46 @@ public class LeAudioService extends ProfileService {
        boolean newSupportedByDeviceOutput = (newSupportedAudioDirections
                & AUDIO_DIRECTION_OUTPUT_BIT) != 0;


        if (device != null && mPreviousAudioOutDevice != null) {
            int previousGroupId = getGroupId(mPreviousAudioOutDevice);
        if (device != null && mActiveAudioOutDevice != null) {
            int previousGroupId = getGroupId(mActiveAudioOutDevice);
            if (previousGroupId == groupId) {
                /* This is the same group as already notified to the system.
                * Therefore do not change the device we have connected to the group,
                * unless, previous one is disconnected now
                */
             if (mPreviousAudioOutDevice.isConnected())
                device = mPreviousAudioOutDevice;
                if (mActiveAudioOutDevice.isConnected()) {
                    device = mActiveAudioOutDevice;
                }
            }

         /* Disconnect output:
         * - If active output device changed (to none or any)
         * - If device stops supporting output
         */
        boolean outActiveDeviceReplace = (device != mPreviousAudioOutDevice);
        if (outActiveDeviceReplace && (mPreviousAudioOutDevice != null)) {
            boolean suppressNoisyIntent =
                    (getConnectionState(mPreviousAudioOutDevice) ==
                    BluetoothProfile.STATE_CONNECTED);
            mAudioManager.setBluetoothLeAudioOutDeviceConnectionState(
                    mPreviousAudioOutDevice, BluetoothProfile.STATE_DISCONNECTED,
                    suppressNoisyIntent);
        }

        mPreviousAudioOutDevice = device;
        BluetoothDevice previousOutDevice = mActiveAudioOutDevice;

        if (device == null) {
            Log.d(TAG,  " device is null.");
            return outActiveDeviceReplace;
        }

        if (outActiveDeviceReplace == false ||
            (oldSupportedByDeviceOutput == newSupportedByDeviceOutput)) {
            Log.d(TAG,  " Nothing to do.");
            return outActiveDeviceReplace;
        /*
         * Do not update output if neither previous nor current device support output
         */
        if (!oldSupportedByDeviceOutput && !newSupportedByDeviceOutput) {
            Log.d(TAG, "updateActiveOutDevice: Device does not support output.");
            return false;
        }

        /* Connect output:
         * - If active output device changed
         * - If device starts support output
        /*
         * Update output if:
         * - Device changed
         *     OR
         * - Device stops / starts supporting output
         */
         mAudioManager.setBluetoothLeAudioOutDeviceConnectionState(
                    device, BluetoothProfile.STATE_CONNECTED, true);
        return outActiveDeviceReplace;
        if (!Objects.equals(device, previousOutDevice)
                || (oldSupportedByDeviceOutput != newSupportedByDeviceOutput)) {
            mActiveAudioOutDevice = newSupportedByDeviceOutput ? device : null;
            final boolean suppressNoisyIntent = (mActiveAudioOutDevice != null)
                    || (getConnectionState(previousOutDevice) == BluetoothProfile.STATE_CONNECTED);
            mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioOutDevice,
                    previousOutDevice, BtProfileConnectionInfo.leAudio(suppressNoisyIntent, true));
            return true;
        }
        Log.d(TAG, "updateActiveOutDevice: Nothing to do.");
        return false;
    }

    /**
@@ -786,13 +775,12 @@ public class LeAudioService extends ProfileService {

        boolean outReplaced =
            updateActiveOutDevice(device, groupId, oldActiveContexts, newActiveContexts);

        boolean inReplaced =
            updateActiveInDevice(device, groupId, oldActiveContexts, newActiveContexts);

        if (outReplaced || inReplaced) {
            Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mPreviousAudioOutDevice);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mActiveAudioOutDevice);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            sendBroadcast(intent, BLUETOOTH_CONNECT);
+5 −6
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.BtProfileConnectionInfo;
import android.os.Looper;
import android.os.ParcelUuid;

@@ -521,9 +522,8 @@ public class HearingAidServiceTest {
        Assert.assertTrue(mService.getConnectedDevices().contains(mRightDevice));

        // Verify the audio is routed to Hearing Aid Profile
        verify(mAudioManager).setBluetoothHearingAidDeviceConnectionState(
                any(BluetoothDevice.class), eq(BluetoothProfile.STATE_CONNECTED),
                eq(true), eq(0));
        verify(mAudioManager).handleBluetoothActiveDeviceChanged(
                any(BluetoothDevice.class), eq(null), any(BtProfileConnectionInfo.class));

        // Send a disconnect request
        Assert.assertTrue("Disconnect failed", mService.disconnect(mLeftDevice));
@@ -570,9 +570,8 @@ public class HearingAidServiceTest {
        Assert.assertFalse(mService.getConnectedDevices().contains(mRightDevice));

        // Verify the audio is not routed to Hearing Aid Profile
        verify(mAudioManager).setBluetoothHearingAidDeviceConnectionState(
                any(BluetoothDevice.class), eq(BluetoothProfile.STATE_DISCONNECTED),
                eq(false), eq(0));
        verify(mAudioManager).handleBluetoothActiveDeviceChanged(
                eq(null), any(BluetoothDevice.class), any(BtProfileConnectionInfo.class));
    }

    /**