Merge "StatsLog BleScanResults moved out of BatteryStats"
diff --git a/jni/com_android_bluetooth_avrcp_controller.cpp b/jni/com_android_bluetooth_avrcp_controller.cpp
index 8dc9c86..c6fb866 100644
--- a/jni/com_android_bluetooth_avrcp_controller.cpp
+++ b/jni/com_android_bluetooth_avrcp_controller.cpp
@@ -47,6 +47,7 @@
 static jmethodID method_handleSetBrowsedPlayerRsp;
 static jmethodID method_handleSetAddressedPlayerRsp;
 static jmethodID method_handleAddressedPlayerChanged;
+static jmethodID method_handleNowPlayingContentChanged;
 
 static jclass class_MediaBrowser_MediaItem;
 static jclass class_AvrcpPlayer;
@@ -591,6 +592,17 @@
                                method_handleAddressedPlayerChanged, (jint)id);
 }
 
+static void btavrcp_now_playing_content_changed_callback(
+    const RawAddress& bd_addr) {
+  ALOGI("%s", __func__);
+
+  CallbackEnv sCallbackEnv(__func__);
+  if (!sCallbackEnv.valid()) return;
+
+  sCallbackEnv->CallVoidMethod(sCallbacksObj,
+                               method_handleNowPlayingContentChanged);
+}
+
 static btrc_ctrl_callbacks_t sBluetoothAvrcpCallbacks = {
     sizeof(sBluetoothAvrcpCallbacks),
     btavrcp_passthrough_response_callback,
@@ -609,7 +621,8 @@
     btavrcp_change_path_callback,
     btavrcp_set_browsed_player_callback,
     btavrcp_set_addressed_player_callback,
-    btavrcp_addressed_player_changed_callback};
+    btavrcp_addressed_player_changed_callback,
+    btavrcp_now_playing_content_changed_callback};
 
 static void classInitNative(JNIEnv* env, jclass clazz) {
   method_handlePassthroughRsp =
@@ -673,6 +686,8 @@
       env->GetMethodID(clazz, "handleSetAddressedPlayerRsp", "(I)V");
   method_handleAddressedPlayerChanged =
       env->GetMethodID(clazz, "handleAddressedPlayerChanged", "(I)V");
+  method_handleNowPlayingContentChanged =
+      env->GetMethodID(clazz, "handleNowPlayingContentChanged", "()V");
 
   ALOGI("%s: succeeds", __func__);
 }
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 17023e4..846e0ab 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -237,6 +237,7 @@
     <string name="process" translate="false"><xliff:g id="x" /></string>
 
 
+    <string name="bluetooth_a2dp_sink_queue_name">Now Playing</string>
     <string name="bluetooth_map_settings_save">Save</string>
     <string name="bluetooth_map_settings_cancel">Cancel</string>
     <string name="bluetooth_map_settings_intro">Select the accounts you want to share through Bluetooth. You still have to accept any access to the accounts when connecting.</string>
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
index 2580e24..f6ce92f 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
@@ -904,6 +904,14 @@
         mAvrcpCtSm.sendMessage(msg);
     }
 
+    private void handleNowPlayingContentChanged() {
+        if (DBG) {
+            Log.d(TAG, "handleNowPlayingContentChanged");
+        }
+        mAvrcpCtSm.sendMessage(
+                AvrcpControllerStateMachine.MESSAGE_PROCESS_NOW_PLAYING_CONTENTS_CHANGED);
+    }
+
     @Override
     public void dump(StringBuilder sb) {
         super.dump(sb);
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
index a55675a..a672255 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java
@@ -68,6 +68,7 @@
     static final int MESSAGE_PROCESS_SET_BROWSED_PLAYER = 113;
     static final int MESSAGE_PROCESS_SET_ADDRESSED_PLAYER = 114;
     static final int MESSAGE_PROCESS_ADDRESSED_PLAYER_CHANGED = 115;
+    static final int MESSAGE_PROCESS_NOW_PLAYING_CONTENTS_CHANGED = 116;
 
     // commands for connection
     static final int MESSAGE_PROCESS_RC_FEATURES = 301;
@@ -361,7 +362,6 @@
                         boolean updateTrack =
                                 mAddressedPlayer.updateCurrentTrack((TrackInfo) msg.obj);
                         if (updateTrack) {
-                            mBrowseTree.mNowPlayingNode.setCached(false);
                             broadcastMetaDataChanged(
                                     mAddressedPlayer.getCurrentTrack().getMediaMetaData());
                         }
@@ -398,6 +398,12 @@
                         sendMessage(MESSAGE_PROCESS_SET_ADDRESSED_PLAYER);
                         break;
 
+                    case MESSAGE_PROCESS_NOW_PLAYING_CONTENTS_CHANGED:
+                        mBrowseTree.mNowPlayingNode.setCached(false);
+                        mGetFolderList.setFolder(mBrowseTree.mNowPlayingNode.getID());
+                        transitionTo(mGetFolderList);
+                        break;
+
                     default:
                         Log.d(TAG, "Unhandled message" + msg.what);
                         return false;
diff --git a/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayer.java b/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayer.java
index 6dbe6b7..e3cc2db 100644
--- a/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayer.java
+++ b/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayer.java
@@ -118,7 +118,8 @@
                 break;
         }
         return new PlaybackState.Builder().setState(mPlayStatus, position, speed)
-            .setActions(mAvailableActions).build();
+            .setActions(mAvailableActions).setActiveQueueItemId(mCurrentTrack.mTrackNum - 1)
+            .build();
     }
 
     public synchronized boolean updateCurrentTrack(TrackInfo update) {
diff --git a/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java b/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java
index 4478ca2..ccd8888 100644
--- a/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java
+++ b/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java
@@ -41,6 +41,7 @@
 import com.android.bluetooth.a2dpsink.A2dpSinkService;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -106,7 +107,7 @@
     private int mCurrentlyHeldKey = 0;
 
     // Browsing related structures.
-    private List<MediaItem> mNowPlayingList = null;
+    private List<MediaSession.QueueItem> mMediaQueue = new ArrayList<>();
 
     private static final class AvrcpCommandQueueHandler extends Handler {
         WeakReference<BluetoothMediaBrowserService> mInst;
@@ -168,6 +169,8 @@
         mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS
                 | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
         mSession.setActive(true);
+        mSession.setQueueTitle(getString(R.string.bluetooth_a2dp_sink_queue_name));
+        mSession.setQueue(mMediaQueue);
         mAvrcpCommandQueue = new AvrcpCommandQueueHandler(Looper.getMainLooper(), this);
 
         refreshInitialPlayingState();
@@ -284,6 +287,16 @@
         }
 
         @Override
+        public void onSkipToQueueItem(long id) {
+            if (DBG) Log.d(TAG, "onSkipToQueueItem" + id);
+            MediaSession.QueueItem queueItem = mMediaQueue.get((int) id);
+            if (queueItem != null) {
+                String mediaId = queueItem.getDescription().getMediaId();
+                mAvrcpCtrlSrvc.fetchAttrAndPlayItem(mA2dpDevice, mediaId);
+            }
+        }
+
+        @Override
         public void onStop() {
             if (DBG) Log.d(TAG, "onStop");
             mAvrcpCommandQueue.obtainMessage(MSG_AVRCP_PASSTHRU,
@@ -455,6 +468,8 @@
         mA2dpDevice = null;
         mBrowseConnected = false;
         // update playerList.
+        mMediaQueue.clear();
+        mSession.setQueue(mMediaQueue);
         notifyChildrenChanged("__ROOT__");
     }
 
@@ -562,6 +577,7 @@
     private void msgFolderList(Intent intent) {
         // Parse the folder list for children list and id.
         String id = intent.getStringExtra(AvrcpControllerService.EXTRA_FOLDER_ID);
+        updateNowPlayingQueue();
         if (VDBG) Log.d(TAG, "Parent: " + id);
         synchronized (this) {
             // If we have a result object then we should send the result back
@@ -578,6 +594,16 @@
         }
     }
 
+    private void updateNowPlayingQueue() {
+        List<MediaItem> songList = mAvrcpCtrlSrvc.getContents(mA2dpDevice, "NOW_PLAYING");
+        Log.d(TAG, "NowPlaying" + songList.size());
+        mMediaQueue.clear();
+        for (MediaItem song : songList) {
+            mMediaQueue.add(new MediaSession.QueueItem(song.getDescription(), mMediaQueue.size()));
+        }
+        mSession.setQueue(mMediaQueue);
+    }
+
     /**
      * processInternalEvent(Intent intent)
      * Routine to provide MediaBrowserService with content updates from within the same process.
diff --git a/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java b/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java
index 17a192a..1fb498a 100644
--- a/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java
+++ b/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java
@@ -78,7 +78,6 @@
         mNowPlayingNode.mBrowseScope = AvrcpControllerService.BROWSE_SCOPE_NOW_PLAYING;
         mNowPlayingNode.setExpectedChildren(255);
         mBrowseMap.put(ROOT, mRootNode);
-        mRootNode.mChildren.add(mNowPlayingNode);
         mBrowseMap.put(NOW_PLAYING_PREFIX, mNowPlayingNode);
 
         mCurrentBrowseNode = mRootNode;
@@ -208,11 +207,6 @@
                     mBrowseMap.remove(child.getID());
                 }
                 mChildren.clear();
-                if (this == mRootNode) {
-                    mNowPlayingNode.setCached(false);
-                    mRootNode.mChildren.add(mNowPlayingNode);
-                    mBrowseMap.put(NOW_PLAYING_PREFIX, mNowPlayingNode);
-                }
             }
         }
 
diff --git a/src/com/android/bluetooth/avrcpcontroller/TrackInfo.java b/src/com/android/bluetooth/avrcpcontroller/TrackInfo.java
index e89fb4c..7764e60 100644
--- a/src/com/android/bluetooth/avrcpcontroller/TrackInfo.java
+++ b/src/com/android/bluetooth/avrcpcontroller/TrackInfo.java
@@ -58,7 +58,7 @@
     private final String mTrackTitle;
     private final String mAlbumTitle;
     private final String mGenre;
-    private final long mTrackNum; // number of audio file on original recording.
+    final long mTrackNum; // number of audio file on original recording.
     private final long mTotalTracks; // total number of tracks on original recording
     private final long mTrackLen; // full length of AudioFile.
 
diff --git a/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnection.java b/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnection.java
index 1d2add4..f3cb472 100644
--- a/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnection.java
+++ b/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnection.java
@@ -80,7 +80,6 @@
             return;
         }
 
-        mHeadsetProfile.connectAudio(device);
         setInitializing();
         setDialing();
         finishInitializing();
@@ -265,7 +264,6 @@
         if (!mClosed) {
             mHeadsetProfile.acceptCall(mDevice, BluetoothHeadsetClient.CALL_ACCEPT_NONE);
         }
-        mHeadsetProfile.connectAudio(mDevice);
     }
 
     @Override