NuPlayer2: send notification on helper thread avoid deadlock.

Test: MediaPlayer2 works for local file playback
Bug: 63934228
Change-Id: Idb1f9d865f9060a3886f465147d7c1e45a669455
diff --git a/media/libmedia/include/media/MediaHTTPConnection.h b/media/libmedia/include/media/MediaHTTPConnection.h
index 82a79e5..17813a2 100644
--- a/media/libmedia/include/media/MediaHTTPConnection.h
+++ b/media/libmedia/include/media/MediaHTTPConnection.h
@@ -20,6 +20,8 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
 
 namespace android {
 
diff --git a/media/libmedia/include/media/MediaPlayer2Interface.h b/media/libmedia/include/media/MediaPlayer2Interface.h
index bd1146d..3afad6d 100644
--- a/media/libmedia/include/media/MediaPlayer2Interface.h
+++ b/media/libmedia/include/media/MediaPlayer2Interface.h
@@ -25,13 +25,14 @@
 #include <utils/String8.h>
 #include <utils/RefBase.h>
 
-#include <media/mediaplayer2.h>
 #include <media/AudioResamplerPublic.h>
 #include <media/AudioSystem.h>
 #include <media/AudioTimestamp.h>
 #include <media/AVSyncSettings.h>
 #include <media/BufferingSettings.h>
 #include <media/Metadata.h>
+#include <media/mediaplayer2.h>
+#include <media/stagefright/foundation/AHandler.h>
 
 // Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
 // global, and not in android::
@@ -72,7 +73,7 @@
         int msg, int ext1, int ext2, const Parcel *obj);
 
 // abstract base class - use MediaPlayer2Interface
-class MediaPlayer2Base : public RefBase
+class MediaPlayer2Base : public AHandler
 {
 public:
     // AudioSink: abstraction layer for audio output
@@ -294,6 +295,8 @@
         return INVALID_OPERATION;
     }
 
+    virtual void onMessageReceived(const sp<AMessage> & /* msg */) override { }
+
     // Modular DRM
     virtual status_t prepareDrm(const uint8_t /* uuid */[16], const Vector<uint8_t>& /* drmSessionId */) {
         return INVALID_OPERATION;
diff --git a/media/libmedia/nuplayer2/NuPlayer2Driver.cpp b/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
index c0f0bad..fb99347 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
@@ -41,7 +41,7 @@
 namespace android {
 
 // key for media statistics
-static const char *kKeyPlayer = "nuplayer";
+static const char *kKeyPlayer = "nuplayer2";
 // attrs for media statistics
 static const char *kPlayerVMime = "android.media.mediaplayer.video.mime";
 static const char *kPlayerVCodec = "android.media.mediaplayer.video.codec";
@@ -75,6 +75,7 @@
       mRebufferingEvents(0),
       mRebufferingAtExit(false),
       mLooper(new ALooper),
+      mNuPlayer2Looper(new ALooper),
       mMediaClock(new MediaClock),
       mPlayer(new NuPlayer2(pid, mMediaClock)),
       mPlayerFlags(0),
@@ -85,6 +86,7 @@
       mAutoLoop(false) {
     ALOGD("NuPlayer2Driver(%p) created, clientPid(%d)", this, pid);
     mLooper->setName("NuPlayer2Driver Looper");
+    mNuPlayer2Looper->setName("NuPlayer2 Looper");
 
     mMediaClock->init();
 
@@ -92,18 +94,19 @@
     mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
     mAnalyticsItem->generateSessionID();
 
-    mLooper->start(
+    mNuPlayer2Looper->start(
             false, /* runOnCallingThread */
             true,  /* canCallJava */
             PRIORITY_AUDIO);
 
-    mLooper->registerHandler(mPlayer);
+    mNuPlayer2Looper->registerHandler(mPlayer);
 
     mPlayer->setDriver(this);
 }
 
 NuPlayer2Driver::~NuPlayer2Driver() {
     ALOGV("~NuPlayer2Driver(%p)", this);
+    mNuPlayer2Looper->stop();
     mLooper->stop();
 
     // finalize any pending metrics, usually a no-op.
@@ -117,6 +120,12 @@
 }
 
 status_t NuPlayer2Driver::initCheck() {
+    mLooper->start(
+            false, /* runOnCallingThread */
+            true,  /* canCallJava */
+            PRIORITY_AUDIO);
+
+    mLooper->registerHandler(this);
     return OK;
 }
 
@@ -381,7 +390,7 @@
 
         case STATE_PAUSED:
             mState = STATE_STOPPED;
-            notifyListener_l(MEDIA2_STOPPED);
+            sendNotifyOnLooper(MEDIA2_STOPPED);
             break;
 
         case STATE_PREPARED:
@@ -416,7 +425,7 @@
 
         case STATE_RUNNING:
             mState = STATE_PAUSED;
-            notifyListener_l(MEDIA2_PAUSED);
+            sendNotifyOnLooper(MEDIA2_PAUSED);
             mPlayer->pause();
             break;
 
@@ -440,7 +449,7 @@
         Mutex::Autolock autoLock(mLock);
         if (rate.mSpeed == 0.f && mState == STATE_RUNNING) {
             mState = STATE_PAUSED;
-            notifyListener_l(MEDIA2_PAUSED);
+            sendNotifyOnLooper(MEDIA2_PAUSED);
         } else if (rate.mSpeed != 0.f
                 && (mState == STATE_PAUSED
                     || mState == STATE_STOPPED_AND_PREPARED
@@ -478,7 +487,7 @@
             mAtEOS = false;
             mSeekInProgress = true;
             // seeks can take a while, so we essentially paused
-            notifyListener_l(MEDIA2_PAUSED);
+            sendNotifyOnLooper(MEDIA2_PAUSED);
             mPlayer->seekToAsync(seekTimeUs, mode, true /* needNotify */);
             break;
         }
@@ -651,7 +660,7 @@
         {
             CHECK(mIsAsyncPrepare);
 
-            notifyListener_l(MEDIA2_PREPARED);
+            sendNotifyOnLooper(MEDIA2_PREPARED);
             break;
         }
 
@@ -660,7 +669,7 @@
     }
 
     if (mState != STATE_STOPPED) {
-        notifyListener_l(MEDIA2_STOPPED);
+        sendNotifyOnLooper(MEDIA2_STOPPED);
     }
 
     mState = STATE_RESET_IN_PROGRESS;
@@ -704,7 +713,7 @@
     int32_t methodId;
     status_t ret = request.readInt32(&methodId);
     if (ret != OK) {
-        ALOGE("Failed to retrieve the requested method to invoke");
+        ALOGE("Failed to retrieve the requested method to invoke, err(%d)", ret);
         return ret;
     }
 
@@ -939,6 +948,19 @@
     return OK;
 }
 
+void NuPlayer2Driver::onMessageReceived(const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatNotifyListener: {
+            int32_t msgId;
+            CHECK(msg->findInt32("messageId", &msgId));
+            notifyListener(msgId);
+            break;
+        }
+        default:
+            break;
+    }
+}
+
 void NuPlayer2Driver::notifyListener(
         int msg, int ext1, int ext2, const Parcel *in) {
     Mutex::Autolock autoLock(mLock);
@@ -1007,6 +1029,12 @@
     mLock.lock();
 }
 
+void NuPlayer2Driver::sendNotifyOnLooper(int msgId) {
+    sp<AMessage> msg = new AMessage(kWhatNotifyListener, this);
+    msg->setInt32("messageId", msgId);
+    msg->post();
+}
+
 void NuPlayer2Driver::notifySetDataSourceCompleted(status_t err) {
     Mutex::Autolock autoLock(mLock);
 
diff --git a/media/libmedia/nuplayer2/NuPlayer2Driver.h b/media/libmedia/nuplayer2/NuPlayer2Driver.h
index edd4556..051eba5 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Driver.h
+++ b/media/libmedia/nuplayer2/NuPlayer2Driver.h
@@ -78,6 +78,8 @@
 
     virtual status_t dump(int fd, const Vector<String16> &args) const;
 
+    virtual void onMessageReceived(const sp<AMessage> &msg) override;
+
     void notifySetDataSourceCompleted(status_t err);
     void notifyPrepareCompleted(status_t err);
     void notifyResetComplete();
@@ -113,6 +115,10 @@
         STATE_STOPPED_AND_PREPARED,     // equivalent to PAUSED, but seek complete
     };
 
+    enum {
+        kWhatNotifyListener,
+    };
+
     mutable Mutex mLock;
     Condition mCondition;
 
@@ -134,6 +140,7 @@
     // <<<
 
     sp<ALooper> mLooper;
+    sp<ALooper> mNuPlayer2Looper;
     const sp<MediaClock> mMediaClock;
     const sp<NuPlayer2> mPlayer;
     sp<AudioSink> mAudioSink;
@@ -146,13 +153,13 @@
     bool mLooping;
     bool mAutoLoop;
 
-
     void updateMetrics(const char *where);
     void logMetrics(const char *where);
 
     status_t prepare_l();
     status_t start_l();
     void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
+    void sendNotifyOnLooper(int msgId);
 
     DISALLOW_EVIL_CONSTRUCTORS(NuPlayer2Driver);
 };