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

Commit 938b0a78 authored by Ugo Yu's avatar Ugo Yu Committed by Hansong Zhang
Browse files

A2DP: Don't suppress noisy intent while stopping A2dpService

- While stopping A2dpService, setActiveDevice(null) is called to
  notify AudioManager the disconnection. However, if A2DP is streaming,
  music won't be stopped by this notification since noisy intent has
  been suppressed due to A2DP is actually still connected.
- Add a function removeActiveDevice() to handle events which needs
  AudioManager to send noisy intent no matter the conection state is.
- Also, we need to store AVRCP volume level since setActiveDevice
  is replaced by removeActiveDevice in A2dpService.stop.

Bug: 80376490
Test: runtest bluetooth -j48
      Turn off Bluetooth while playing A2DP streaming

Change-Id: Ied9efcb608ff5235551a06b5462379ed7a754b6a
Merged-In: Ied9efcb608ff5235551a06b5462379ed7a754b6a
(cherry picked from commit 2fcd01c2)
parent e2ddacd9
Loading
Loading
Loading
Loading
+42 −25
Original line number Diff line number Diff line
@@ -166,8 +166,13 @@ public class A2dpService extends ProfileService {
            return true;
        }

        // Step 9: Clear active device
        setActiveDevice(null);
        // Step 10: Store volume if there is an active device
        if (mActiveDevice != null && AvrcpTargetService.get() != null) {
            AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice);
        }

        // Step 9: Clear active device and stop playing audio
        removeActiveDevice(true);

        // Step 8: Mark service as stopped
        setA2dpService(null);
@@ -425,6 +430,39 @@ public class A2dpService extends ProfileService {
        }
    }

    private void removeActiveDevice(boolean forceStopPlayingAudio) {
        BluetoothDevice previousActiveDevice = mActiveDevice;
        synchronized (mStateMachines) {
            // Clear the active device
            mActiveDevice = null;
            // This needs to happen before we inform the audio manager that the device
            // disconnected. Please see comment in broadcastActiveDevice() for why.
            broadcastActiveDevice(null);

            if (previousActiveDevice == null) {
                return;
            }

            // Make sure the Audio Manager knows the previous Active device is disconnected.
            // However, if A2DP is still connected and not forcing stop audio for that remote
            // 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);
            // Make sure the Active device in native layer is set to null and audio is off
            if (!mA2dpNativeInterface.setActiveDevice(null)) {
                Log.w(TAG, "setActiveDevice(null): Cannot remove active device in native "
                        + "layer");
            }
        }
    }

    /**
     * Set the active device.
     *
@@ -444,29 +482,8 @@ public class A2dpService extends ProfileService {
            }

            if (device == null) {
                // Clear the active device
                mActiveDevice = null;
                // This needs to happen before we inform the audio manager that the device
                // disconnected. Please see comment in broadcastActiveDevice() for why.
                broadcastActiveDevice(null);
                if (previousActiveDevice != null) {
                    // Make sure the Audio Manager knows the previous Active device is disconnected.
                    // However, if A2DP is still connected for that remote 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.
                    mAudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
                            previousActiveDevice, BluetoothProfile.STATE_DISCONNECTED,
                            BluetoothProfile.A2DP,
                            getConnectionState(previousActiveDevice)
                                == BluetoothProfile.STATE_CONNECTED, -1);
                    // Make sure the Active device in native layer is set to null and audio is off
                    if (!mA2dpNativeInterface.setActiveDevice(null)) {
                        Log.w(TAG, "setActiveDevice(null): Cannot remove active device in native "
                                + "layer");
                    }
                }
                // Remove active device and continue playing audio only if necessary.
                removeActiveDevice(false);
                return true;
            }