Merge "Added device info playback config for native players"
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 57c4c16..431f0fa 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -171,7 +171,7 @@
     aaudio_result_t result = requestStart_l();
     if (result == AAUDIO_OK) {
         // We only call this for logging in "dumpsys audio". So ignore return code.
-        (void) mPlayerBase->start();
+        (void) mPlayerBase->startWithStatus(getDeviceId());
     }
     return result;
 }
@@ -221,7 +221,7 @@
     aaudio_result_t result = requestPause_l();
     if (result == AAUDIO_OK) {
         // We only call this for logging in "dumpsys audio". So ignore return code.
-        (void) mPlayerBase->pause();
+        (void) mPlayerBase->pauseWithStatus();
     }
     return result;
 }
@@ -251,7 +251,7 @@
     aaudio_result_t result = safeStop_l();
     if (result == AAUDIO_OK) {
         // We only call this for logging in "dumpsys audio". So ignore return code.
-        (void) mPlayerBase->stop();
+        (void) mPlayerBase->stopWithStatus();
     }
     return result;
 }
@@ -265,7 +265,7 @@
     aaudio_result_t result = safeStop_l();
     if (result == AAUDIO_OK) {
         // We only call this for logging in "dumpsys audio". So ignore return code.
-        (void) mPlayerBase->stop();
+        (void) mPlayerBase->stopWithStatus();
     }
     return result;
 }
diff --git a/media/libaudioclient/PlayerBase.cpp b/media/libaudioclient/PlayerBase.cpp
index 9e7d89e..8793735 100644
--- a/media/libaudioclient/PlayerBase.cpp
+++ b/media/libaudioclient/PlayerBase.cpp
@@ -30,7 +30,8 @@
 PlayerBase::PlayerBase() : BnPlayer(),
         mPanMultiplierL(1.0f), mPanMultiplierR(1.0f),
         mVolumeMultiplierL(1.0f), mVolumeMultiplierR(1.0f),
-        mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN)
+        mPIId(PLAYER_PIID_INVALID), mLastReportedEvent(PLAYER_STATE_UNKNOWN),
+        mLastReportedDeviceId(AUDIO_PORT_HANDLE_NONE)
 {
     ALOGD("PlayerBase::PlayerBase()");
     // use checkService() to avoid blocking if audio service is not up yet
@@ -64,14 +65,26 @@
 }
 
 //------------------------------------------------------------------------------
-void PlayerBase::servicePlayerEvent(player_state_t event) {
+void PlayerBase::servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId) {
     if (mAudioManager != 0) {
-        // only report state change
-        Mutex::Autolock _l(mPlayerStateLock);
-        if (event != mLastReportedEvent
-                && mPIId != PLAYER_PIID_INVALID) {
-            mLastReportedEvent = event;
-            mAudioManager->playerEvent(mPIId, event);
+        bool changed = false;
+        {
+            Mutex::Autolock _l(mDeviceIdLock);
+            changed = mLastReportedDeviceId != deviceId;
+            mLastReportedDeviceId = deviceId;
+        }
+
+        {
+            Mutex::Autolock _l(mPlayerStateLock);
+            // PLAYER_UPDATE_DEVICE_ID is not saved as an actual state, instead it is used to update
+            // device ID only.
+            if ((event != PLAYER_UPDATE_DEVICE_ID) && (event != mLastReportedEvent)) {
+                mLastReportedEvent = event;
+                changed = true;
+            }
+        }
+        if (changed && (mPIId != PLAYER_PIID_INVALID)) {
+            mAudioManager->playerEvent(mPIId, event, deviceId);
         }
     }
 }
@@ -84,14 +97,18 @@
 }
 
 //FIXME temporary method while some player state is outside of this class
-void PlayerBase::reportEvent(player_state_t event) {
-    servicePlayerEvent(event);
+void PlayerBase::reportEvent(player_state_t event, audio_port_handle_t deviceId) {
+    servicePlayerEvent(event, deviceId);
 }
 
-status_t PlayerBase::startWithStatus() {
+void PlayerBase::baseUpdateDeviceId(audio_port_handle_t deviceId) {
+    servicePlayerEvent(PLAYER_UPDATE_DEVICE_ID, deviceId);
+}
+
+status_t PlayerBase::startWithStatus(audio_port_handle_t deviceId) {
     status_t status = playerStart();
     if (status == NO_ERROR) {
-        servicePlayerEvent(PLAYER_STATE_STARTED);
+        servicePlayerEvent(PLAYER_STATE_STARTED, deviceId);
     } else {
         ALOGW("PlayerBase::start() error %d", status);
     }
@@ -101,18 +118,18 @@
 status_t PlayerBase::pauseWithStatus() {
     status_t status = playerPause();
     if (status == NO_ERROR) {
-        servicePlayerEvent(PLAYER_STATE_PAUSED);
+        servicePlayerEvent(PLAYER_STATE_PAUSED, AUDIO_PORT_HANDLE_NONE);
     } else {
         ALOGW("PlayerBase::pause() error %d", status);
     }
     return status;
 }
 
-
 status_t PlayerBase::stopWithStatus() {
     status_t status = playerStop();
+
     if (status == NO_ERROR) {
-        servicePlayerEvent(PLAYER_STATE_STOPPED);
+        servicePlayerEvent(PLAYER_STATE_STOPPED, AUDIO_PORT_HANDLE_NONE);
     } else {
         ALOGW("PlayerBase::stop() error %d", status);
     }
@@ -123,7 +140,12 @@
 // Implementation of IPlayer
 binder::Status PlayerBase::start() {
     ALOGD("PlayerBase::start() from IPlayer");
-    (void)startWithStatus();
+    audio_port_handle_t deviceId;
+    {
+        Mutex::Autolock _l(mDeviceIdLock);
+        deviceId = mLastReportedDeviceId;
+    }
+    (void)startWithStatus(deviceId);
     return binder::Status::ok();
 }
 
diff --git a/media/libaudioclient/TrackPlayerBase.cpp b/media/libaudioclient/TrackPlayerBase.cpp
index 372b7c3..5c73756 100644
--- a/media/libaudioclient/TrackPlayerBase.cpp
+++ b/media/libaudioclient/TrackPlayerBase.cpp
@@ -36,6 +36,10 @@
 void TrackPlayerBase::init(AudioTrack* pat, player_type_t playerType, audio_usage_t usage) {
     PlayerBase::init(playerType, usage);
     mAudioTrack = pat;
+    if (mAudioTrack != 0) {
+        mSelfAudioDeviceCallback = new SelfAudioDeviceCallback(*this);
+        mAudioTrack->addAudioDeviceCallback(mSelfAudioDeviceCallback);
+    }
 }
 
 void TrackPlayerBase::destroy() {
@@ -43,9 +47,23 @@
     baseDestroy();
 }
 
+TrackPlayerBase::SelfAudioDeviceCallback::SelfAudioDeviceCallback(PlayerBase& self) :
+    AudioSystem::AudioDeviceCallback(), mSelf(self) {
+}
+
+TrackPlayerBase::SelfAudioDeviceCallback::~SelfAudioDeviceCallback() {
+}
+
+void TrackPlayerBase::SelfAudioDeviceCallback::onAudioDeviceUpdate(audio_io_handle_t __unused,
+                                                                   audio_port_handle_t deviceId) {
+    mSelf.baseUpdateDeviceId(deviceId);
+}
+
 void TrackPlayerBase::doDestroy() {
     if (mAudioTrack != 0) {
         mAudioTrack->stop();
+        mAudioTrack->removeAudioDeviceCallback(mSelfAudioDeviceCallback);
+        mSelfAudioDeviceCallback.clear();
         // Note that there may still be another reference in post-unlock phase of SetPlayState
         mAudioTrack.clear();
     }
diff --git a/media/libaudioclient/include/media/PlayerBase.h b/media/libaudioclient/include/media/PlayerBase.h
index 4aad9b4..1a42b88 100644
--- a/media/libaudioclient/include/media/PlayerBase.h
+++ b/media/libaudioclient/include/media/PlayerBase.h
@@ -44,12 +44,14 @@
             const media::VolumeShaperConfiguration& configuration,
             const media::VolumeShaperOperation& operation) override;
 
-            status_t startWithStatus();
+            status_t startWithStatus(audio_port_handle_t deviceId);
             status_t pauseWithStatus();
             status_t stopWithStatus();
 
             //FIXME temporary method while some player state is outside of this class
-            void reportEvent(player_state_t event);
+            void reportEvent(player_state_t event, audio_port_handle_t deviceId);
+
+            void baseUpdateDeviceId(audio_port_handle_t deviceId);
 
 protected:
 
@@ -71,7 +73,7 @@
 
 private:
             // report events to AudioService
-            void servicePlayerEvent(player_state_t event);
+            void servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId);
             void serviceReleasePlayer();
 
     // native interface to AudioService
@@ -83,6 +85,9 @@
     // Mutex for state reporting
     Mutex mPlayerStateLock;
     player_state_t mLastReportedEvent;
+
+    Mutex mDeviceIdLock;
+    audio_port_handle_t mLastReportedDeviceId;
 };
 
 } // namespace android
diff --git a/media/libaudioclient/include/media/TrackPlayerBase.h b/media/libaudioclient/include/media/TrackPlayerBase.h
index 6d26e63..b40d1eb 100644
--- a/media/libaudioclient/include/media/TrackPlayerBase.h
+++ b/media/libaudioclient/include/media/TrackPlayerBase.h
@@ -53,8 +53,20 @@
             void doDestroy();
             status_t doSetVolume();
 
+            class SelfAudioDeviceCallback : public AudioSystem::AudioDeviceCallback {
+            public:
+                SelfAudioDeviceCallback(PlayerBase& self);
+                virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
+                                                         audio_port_handle_t deviceId);
+            private:
+                virtual ~SelfAudioDeviceCallback();
+                PlayerBase& mSelf;
+            };
+
     // volume coming from the player volume API
     float mPlayerVolumeL, mPlayerVolumeR;
+
+   sp<SelfAudioDeviceCallback> mSelfAudioDeviceCallback;
 };
 
 } // namespace android