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

Commit 9f640e77 authored by Sanket Agarwal's avatar Sanket Agarwal
Browse files

A2DP MediaSession active state management and NPE

UIs (such as SystemUI) depend on MediaSession.isActive state to
determine whether to show it on the overview (or shades). Currently we
are keeping the session active ever since the first bluetooth connect (A2DP) happens.

This change makes the session to be active when the device connects and
the first play happens (i.e. the play state of remote device
irrespective of who initated it) and in-active when device disconnects.

Also, avoid a NPE that may happen due to races between delay in
broadcasts and accesing bluetooth state machine.

Bug: b/28345602
Bug: b/28330860

Change-Id: Id7686308ada0b608b959258d137772ee5f24c18f
(cherry picked from commit ffb10b682610a24d5c54e8828c11276fe5703d65)
parent 79eb35ca
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -51,6 +51,20 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Implements the MediaBrowserService interface to AVRCP and A2DP
 *
 * This service provides a means for external applications to access A2DP and AVRCP.
 * The applications are expected to use MediaBrowser (see API) and all the music
 * browsing/playback/metadata can be controlled via MediaBrowser and MediaController.
 *
 * The current behavior of MediaSession exposed by this service is as follows:
 * 1. MediaSession is active (i.e. SystemUI and other overview UIs can see updates) when device is
 * connected and first starts playing. Before it starts playing we do not active the session.
 * 1.1 The session is active throughout the duration of connection.
 * 2. The session is de-activated when the device disconnects. It will be connected again when (1)
 * happens.
 */
public class A2dpMediaBrowserService extends MediaBrowserService {
    private static final String TAG = "A2dpMediaBrowserService";
    private static final String UNKNOWN_BT_AUDIO = "__UNKNOWN_BT_AUDIO__";
@@ -292,6 +306,11 @@ public class A2dpMediaBrowserService extends MediaBrowserService {
                } else if (state == BluetoothProfile.STATE_DISCONNECTED) {
                    // Set the playback state to unconnected.
                    mAvrcpCommandQueue.obtainMessage(MSG_DEVICE_DISCONNECT, btDev).sendToTarget();
                    // If we have been pushing updates via the session then stop sending them since
                    // we are not connected anymore.
                    if (mSession.isActive()) {
                        mSession.setActive(false);
                    }
                }
            } else if (AvrcpControllerService.ACTION_BROWSE_CONNECTION_STATE_CHANGED.equals(
                action)) {
@@ -409,6 +428,12 @@ public class A2dpMediaBrowserService extends MediaBrowserService {
            PlaybackState.Builder pbb = new PlaybackState.Builder(pb);
            pb = pbb.setActions(mTransportControlFlags).build();
            mSession.setPlaybackState(pb);

            // If we are now playing then we should start pushing updates via MediaSession so that
            // external UI (such as SystemUI) can show the currently playing music.
            if (pb.getState() == PlaybackState.STATE_PLAYING && !mSession.isActive()) {
                mSession.setActive(true);
            }
        }
    }

+8 −0
Original line number Diff line number Diff line
@@ -104,10 +104,18 @@ public class HfpClientConnectionService extends ConnectionService {
                        List<BluetoothHeadsetClientCall> calls =
                                mHeadsetProfile.getCurrentCalls(mDevice);
                        Log.d(TAG, "Got calls " + calls);
                        if (calls == null) {
                            // We can get null as a return if we are not connected. Hence there may
                            // be a race in getting the broadcast and HFP Client getting
                            // disconnected before broadcast gets delivered.
                            Log.w(TAG, "Got connected but calls were null, ignoring the broadcast");
                            return;
                        }
                        for (BluetoothHeadsetClientCall call : calls) {
                            handleCall(call);
                        }
                    } else {
                        Log.e(TAG, "headset profile is null, ignoring broadcast.");
                    }
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    Log.d(TAG, "Disconnecting from " + device);