From ffb10b682610a24d5c54e8828c11276fe5703d65 Mon Sep 17 00:00:00 2001 From: Sanket Agarwal Date: Fri, 22 Apr 2016 13:06:24 -0700 Subject: [PATCH] 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 faa30bec93650414fb90b60b5a488b32dd54b9ac) --- .../a2dpsink/mbs/A2dpMediaBrowserService.java | 26 +++++++++++++++++++++- .../connserv/HfpClientConnectionService.java | 8 +++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/com/android/bluetooth/a2dpsink/mbs/A2dpMediaBrowserService.java b/src/com/android/bluetooth/a2dpsink/mbs/A2dpMediaBrowserService.java index 169f6fff..28dad094 100644 --- a/src/com/android/bluetooth/a2dpsink/mbs/A2dpMediaBrowserService.java +++ b/src/com/android/bluetooth/a2dpsink/mbs/A2dpMediaBrowserService.java @@ -44,6 +44,20 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; +/** + * 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 MEDIA_ID_ROOT = "__ROOT__"; @@ -125,7 +139,6 @@ public class A2dpMediaBrowserService extends MediaBrowserService { mSession.setCallback(mSessionCallbacks); mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); - mSession.setActive(true); mAvrcpCommandQueue = new AvrcpCommandQueueHandler(Looper.getMainLooper(), this); mAdapter = BluetoothAdapter.getDefaultAdapter(); @@ -268,6 +281,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 (BluetoothAvrcpController.ACTION_TRACK_EVENT.equals(action)) { PlaybackState pbb = @@ -386,6 +404,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); + } } } diff --git a/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnectionService.java b/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnectionService.java index a2c2430e..5c50f822 100644 --- a/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnectionService.java +++ b/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnectionService.java @@ -75,10 +75,18 @@ public class HfpClientConnectionService extends ConnectionService { List 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) { // Disconnect any inflight calls from the connection service. -- 2.11.0