Merge cherrypicks of [2937968, 2940489, 2939606, 2939607, 2940434, 2940435, 2940436, 2940437, 2940509, 2940510, 2940118, 2940119, 2940120, 2940121, 2940122, 2938726, 2938728, 2940550, 2940552, 2940554, 2940556, 2940511, 2940512, 2940513, 2940514, 2940515, 2940558, 2940649, 2940650, 2940441, 2940442, 2940559, 2940560, 2940561, 2940562, 2940563, 2940564, 2938336, 2940565, 2940566, 2940516, 2940443, 2940517, 2940444, 2940445] into oc-dr1-release

Change-Id: Iadd1b2252e5d525e5e8fc04a6a2ea1db3c36dc63
diff --git a/src/com/android/bluetooth/avrcp/AddressedMediaPlayer.java b/src/com/android/bluetooth/avrcp/AddressedMediaPlayer.java
index cc0957e..d2c941e 100644
--- a/src/com/android/bluetooth/avrcp/AddressedMediaPlayer.java
+++ b/src/com/android/bluetooth/avrcp/AddressedMediaPlayer.java
@@ -149,7 +149,7 @@
 
     private void sendNowPlayingListChanged() {
         if (mMediaInterface == null) return;
-        mMediaInterface.uidsChangedRsp(AvrcpConstants.NOTIFICATION_TYPE_CHANGED);
+        if (DEBUG) Log.d(TAG, "sendNowPlayingListChanged()");
         mMediaInterface.nowPlayingChangedRsp(AvrcpConstants.NOTIFICATION_TYPE_CHANGED);
         mNowPlayingListUpdated = false;
     }
diff --git a/src/com/android/bluetooth/avrcp/Avrcp.java b/src/com/android/bluetooth/avrcp/Avrcp.java
index 61d7adf..274c10b 100644
--- a/src/com/android/bluetooth/avrcp/Avrcp.java
+++ b/src/com/android/bluetooth/avrcp/Avrcp.java
@@ -371,13 +371,13 @@
         @Override
         public void onMetadataChanged(MediaMetadata metadata) {
             if (DEBUG) Log.v(TAG, "onMetadataChanged");
-            updateCurrentMediaState(false);
+            updateCurrentMediaState();
         }
         @Override
         public synchronized void onPlaybackStateChanged(PlaybackState state) {
             if (DEBUG) Log.v(TAG, "onPlaybackStateChanged: state " + state.toString());
 
-            updateCurrentMediaState(false);
+            updateCurrentMediaState();
         }
 
         @Override
@@ -477,7 +477,7 @@
             case MSG_NOW_PLAYING_CHANGED_RSP:
                 if (DEBUG) Log.v(TAG, "MSG_NOW_PLAYING_CHANGED_RSP");
                 removeMessages(MSG_NOW_PLAYING_CHANGED_RSP);
-                updateCurrentMediaState(false);
+                updateCurrentMediaState();
                 break;
 
             case MSG_PLAY_INTERVAL_TIMEOUT:
@@ -691,7 +691,7 @@
             case MSG_SET_A2DP_AUDIO_STATE:
                 if (DEBUG) Log.v(TAG, "MSG_SET_A2DP_AUDIO_STATE:" + msg.arg1);
                 mA2dpState = msg.arg1;
-                updateCurrentMediaState(false);
+                updateCurrentMediaState();
                 break;
 
             case MSG_NATIVE_REQ_GET_FOLDER_ITEMS: {
@@ -962,36 +962,8 @@
         }
     }
 
-    private void updateCurrentMediaState(boolean registering) {
+    private void updateCurrentMediaState() {
         // Only do player updates when we aren't registering for track changes.
-        if (!registering) {
-            if (mAvailablePlayerViewChanged) {
-                registerNotificationRspAvalPlayerChangedNative(
-                        AvrcpConstants.NOTIFICATION_TYPE_CHANGED);
-                mAvailablePlayerViewChanged = false;
-                return;
-            }
-            if (mAddrPlayerChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM
-                    && mReportedPlayerID != mCurrAddrPlayerID) {
-                registerNotificationRspAvalPlayerChangedNative(
-                        AvrcpConstants.NOTIFICATION_TYPE_CHANGED);
-                mAvailablePlayerViewChanged = false;
-                registerNotificationRspAddrPlayerChangedNative(
-                        AvrcpConstants.NOTIFICATION_TYPE_CHANGED, mCurrAddrPlayerID, sUIDCounter);
-                mAddrPlayerChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
-                // Changing player sends reject to anything else we would notify...
-                mReportedPlayerID = mCurrAddrPlayerID;
-                mPlayStatusChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
-                mTrackChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
-                mPlayPosChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
-                mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
-                mAddressedMediaPlayer.updateNowPlayingList(mMediaController);
-                // If the player changed, they need to re-request anything here again
-                // so we can skip the rest of the update.
-                return;
-            }
-        }
-
         MediaAttributes currentAttributes;
         PlaybackState newState = updatePlaybackState();
 
@@ -1013,6 +985,30 @@
                             + currentAttributes.toRedactedString() + " : "
                             + mMediaAttributes.toRedactedString());
 
+            if (mAvailablePlayerViewChanged) {
+                registerNotificationRspAvalPlayerChangedNative(
+                        AvrcpConstants.NOTIFICATION_TYPE_CHANGED);
+                mAvailablePlayerViewChanged = false;
+                return;
+            }
+
+            if (mAddrPlayerChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM
+                    && mReportedPlayerID != mCurrAddrPlayerID) {
+                registerNotificationRspAvalPlayerChangedNative(
+                        AvrcpConstants.NOTIFICATION_TYPE_CHANGED);
+                registerNotificationRspAddrPlayerChangedNative(
+                        AvrcpConstants.NOTIFICATION_TYPE_CHANGED, mCurrAddrPlayerID, sUIDCounter);
+
+                mAvailablePlayerViewChanged = false;
+                mAddrPlayerChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
+                mReportedPlayerID = mCurrAddrPlayerID;
+
+                // Update the now playing list without sending the notification
+                mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_CHANGED;
+                mAddressedMediaPlayer.updateNowPlayingList(mMediaController);
+                mNowPlayingListChangedNT = AvrcpConstants.NOTIFICATION_TYPE_INTERIM;
+            }
+
             // Dont send now playing list changed if the player doesn't support browsing
             MediaPlayerInfo info = getAddressedPlayerInfo();
             if (info != null && info.isBrowseSupported()) {
@@ -1029,21 +1025,25 @@
                 // to update their metadata. Hold of on sending the playback state
                 // update until after we know the current metadata is up to date
                 // and track changed has been sent. This was seen on BMW carkits
-                Log.i(TAG, "Waiting for metadata update to send track changed");
+                Log.i(TAG,
+                        "Waiting for metadata update to send track changed: " + newQueueId + " : "
+                                + currentAttributes + " : " + mMediaAttributes);
 
                 return;
             }
 
             // Notify track changed if:
-            //  - The CT is registering for the notification
+            //  - The CT is registered for the notification
             //  - Queue ID is UNKNOWN and MediaMetadata is different
-            //  - Queue ID is valid and different and MediaMetadata is different
-            if (registering || ((newQueueId == -1 || newQueueId != mLastQueueId)
-                                       && !currentAttributes.equals(mMediaAttributes))) {
+            //  - Queue ID is valid and different from last Queue ID sent
+            if ((newQueueId == -1 || newQueueId != mLastQueueId)
+                    && mTrackChangedNT == AvrcpConstants.NOTIFICATION_TYPE_INTERIM
+                    && !currentAttributes.equals(mMediaAttributes)
+                    && newPlayStatus == PLAYSTATUS_PLAYING) {
                 Log.v(TAG, "Send track changed");
                 mMediaAttributes = currentAttributes;
                 mLastQueueId = newQueueId;
-                sendTrackChangedRsp(registering);
+                sendTrackChangedRsp(false);
             }
         } else {
             Log.i(TAG, "Skipping update due to invalid playback state");
@@ -1631,7 +1631,7 @@
                             Log.v(TAG, "No addressed player but active sessions, taking first.");
                         setAddressedMediaSessionPackage(newControllers.get(0).getPackageName());
                     }
-                    updateCurrentMediaState(false);
+                    updateCurrentMediaState();
                 }
             };
 
@@ -1651,7 +1651,7 @@
         // If the player doesn't exist, we need to add it.
         if (getMediaPlayerInfo(packageName) == null) {
             addMediaPlayerPackage(packageName);
-            updateCurrentMediaState(false);
+            updateCurrentMediaState();
         }
         synchronized (mMediaPlayerInfoList) {
             for (Map.Entry<Integer, MediaPlayerInfo> entry : mMediaPlayerInfoList.entrySet()) {
@@ -1659,7 +1659,7 @@
                     int newAddrID = entry.getKey();
                     if (DEBUG) Log.v(TAG, "Set addressed #" + newAddrID + " " + entry.getValue());
                     updateCurrentController(newAddrID, mCurrBrowsePlayerID);
-                    updateCurrentMediaState(false);
+                    updateCurrentMediaState();
                     return;
                 }
             }
@@ -1740,7 +1740,7 @@
                     addMediaPlayerPackage(packageName);
                 }
             }
-            updateCurrentMediaState(false);
+            updateCurrentMediaState();
         }
     }
 
@@ -1764,7 +1764,7 @@
                 addMediaPlayerController(controller);
             }
 
-            updateCurrentMediaState(false);
+            updateCurrentMediaState();
 
             if (mMediaPlayerInfoList.size() > 0) {
                 // Set the first one as the Addressed Player
@@ -2153,7 +2153,7 @@
                 }
             }
         }
-        updateCurrentMediaState(false);
+        updateCurrentMediaState();
         return registerRsp;
     }
 
@@ -2567,6 +2567,7 @@
         if (!KeyEvent.isMediaKey(code)) {
             Log.w(TAG, "Passthrough non-media key " + op + " (code " + code + ") state " + state);
         }
+
         mMediaSessionManager.dispatchMediaKeyEvent(event);
         addKeyPending(event);
     }
diff --git a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
index 11dd48b..a8fcf15 100644
--- a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+++ b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
@@ -435,6 +435,9 @@
                                         + device.getBondState() + ", device=" + device);
                         // reject the connection and stay in Disconnected state itself
                         disconnectHfpNative(getByteAddress(device));
+                        // the other profile connection should be initiated
+                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED,
+                                BluetoothProfile.STATE_DISCONNECTED);
                     }
                     break;
                 case HeadsetHalConstants.CONNECTION_STATE_DISCONNECTING:
@@ -518,6 +521,60 @@
                         case EVENT_TYPE_BIND:
                             processAtBind(event.valueString, event.device);
                             break;
+                        // Unexpected AT commands, we only handle them for comparability reasons
+                        case EVENT_TYPE_VR_STATE_CHANGED:
+                            Log.w(TAG,
+                                    "Pending: Unexpected VR event, device=" + event.device
+                                            + ", state=" + event.valueInt);
+                            processVrEvent(event.valueInt, event.device);
+                            break;
+                        case EVENT_TYPE_DIAL_CALL:
+                            Log.w(TAG, "Pending: Unexpected dial event, device=" + event.device);
+                            processDialCall(event.valueString, event.device);
+                            break;
+                        case EVENT_TYPE_SUBSCRIBER_NUMBER_REQUEST:
+                            Log.w(TAG,
+                                    "Pending: Unexpected subscriber number event for" + event.device
+                                            + ", state=" + event.valueInt);
+                            processSubscriberNumberRequest(event.device);
+                            break;
+                        case EVENT_TYPE_AT_COPS:
+                            Log.w(TAG, "Pending: Unexpected COPS event for " + event.device);
+                            processAtCops(event.device);
+                            break;
+                        case EVENT_TYPE_AT_CLCC:
+                            Log.w(TAG, "Pending: Unexpected CLCC event for" + event.device);
+                            processAtClcc(event.device);
+                            break;
+                        case EVENT_TYPE_UNKNOWN_AT:
+                            Log.w(TAG,
+                                    "Pending: Unexpected unknown AT event for" + event.device
+                                            + ", cmd=" + event.valueString);
+                            processUnknownAt(event.valueString, event.device);
+                            break;
+                        case EVENT_TYPE_KEY_PRESSED:
+                            Log.w(TAG, "Pending: Unexpected key-press event for " + event.device);
+                            processKeyPressed(event.device);
+                            break;
+                        case EVENT_TYPE_BIEV:
+                            Log.w(TAG,
+                                    "Pending: Unexpected BIEV event for " + event.device
+                                            + ", indId=" + event.valueInt
+                                            + ", indVal=" + event.valueInt2);
+                            processAtBiev(event.valueInt, event.valueInt2, event.device);
+                            break;
+                        case EVENT_TYPE_VOLUME_CHANGED:
+                            Log.w(TAG, "Pending: Unexpected volume event for " + event.device);
+                            processVolumeEvent(event.valueInt, event.valueInt2, event.device);
+                            break;
+                        case EVENT_TYPE_ANSWER_CALL:
+                            Log.w(TAG, "Pending: Unexpected answer event for " + event.device);
+                            processAnswerCall(event.device);
+                            break;
+                        case EVENT_TYPE_HANGUP_CALL:
+                            Log.w(TAG, "Pending: Unexpected hangup event for " + event.device);
+                            processHangupCall(event.device);
+                            break;
                         default:
                             Log.e(TAG, "Pending: Unexpected event: " + event.type);
                             break;
@@ -920,11 +977,9 @@
                             processVrEvent(event.valueInt, event.device);
                             break;
                         case EVENT_TYPE_ANSWER_CALL:
-                            // TODO(BT) could answer call happen on Connected state?
                             processAnswerCall(event.device);
                             break;
                         case EVENT_TYPE_HANGUP_CALL:
-                            // TODO(BT) could hangup call happen on Connected state?
                             processHangupCall(event.device);
                             break;
                         case EVENT_TYPE_VOLUME_CHANGED: