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

Commit a91add54 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 03cd5a71)
parent ab2e619d
Loading
Loading
Loading
Loading
+42 −25
Original line number Original line Diff line number Diff line
@@ -166,8 +166,13 @@ public class A2dpService extends ProfileService {
            return true;
            return true;
        }
        }


        // Step 9: Clear active device
        // Step 10: Store volume if there is an active device
        setActiveDevice(null);
        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
        // Step 8: Mark service as stopped
        setA2dpService(null);
        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.
     * Set the active device.
     *
     *
@@ -444,29 +482,8 @@ public class A2dpService extends ProfileService {
            }
            }


            if (device == null) {
            if (device == null) {
                // Clear the active device
                // Remove active device and continue playing audio only if necessary.
                mActiveDevice = null;
                removeActiveDevice(false);
                // 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");
                    }
                }
                return true;
                return true;
            }
            }