Merge "Use define for drm property keys instead of defining as char pointers"
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 50d9a0f..ac770f1 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -80,8 +80,6 @@
     $(TOP)/frameworks/native/include/media/openmax \
     $(TOP)/frameworks/av/include/media/ \
     $(TOP)/frameworks/av/media/libstagefright \
-    $(TOP)/external/icu/icu4c/source/common \
-    $(TOP)/external/icu/icu4c/source/i18n \
     $(call include-path-for, audio-effects) \
     $(call include-path-for, audio-utils)
 
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index a7568b9..4d33d40 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -261,6 +261,7 @@
             size_t size;
             status_t status = decode(fd, offset, length, &sampleRate, &numChannels, &format,
                                      heap, &size);
+            ::close(fd);
             reply->writeInt32(status);
             if (status == NO_ERROR) {
                 reply->writeInt32(sampleRate);
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 7bb154e..6ea522c 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1398,7 +1398,6 @@
 
 Exit:
     if (player != 0) player->reset();
-    ::close(fd);
     return status;
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index a63a940..42977ca 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -663,8 +663,17 @@
                 instantiateDecoder(false, &mVideoDecoder);
             }
 
-            if (mAudioSink != NULL) {
-                if (mOffloadAudio) {
+            // Don't try to re-open audio sink if there's an existing decoder.
+            if (mAudioSink != NULL && mAudioDecoder == NULL) {
+                sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
+                sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
+                audio_stream_type_t streamType = mAudioSink->getAudioStreamType();
+                bool canOffload = canOffloadStream(audioMeta, (videoFormat != NULL),
+                         true /* is_streaming */, streamType);
+                if (canOffload) {
+                    if (!mOffloadAudio) {
+                        mRenderer->signalEnableOffloadAudio();
+                    }
                     // open audio sink early under offload mode.
                     sp<AMessage> format = mSource->getFormat(true /*audio*/);
                     openAudioSink(format, true /*offloadOnly*/);
@@ -901,7 +910,7 @@
                 ALOGV("media rendering started");
                 notifyListener(MEDIA_STARTED, 0, 0);
             } else if (what == Renderer::kWhatAudioOffloadTearDown) {
-                ALOGV("Tear down audio offload, fall back to s/w path");
+                ALOGV("Tear down audio offload, fall back to s/w path if due to error.");
                 int64_t positionUs;
                 CHECK(msg->findInt64("positionUs", &positionUs));
                 int32_t reason;
@@ -913,11 +922,11 @@
                 if (mVideoDecoder != NULL) {
                     mRenderer->flush(false /* audio */);
                 }
-                mRenderer->signalDisableOffloadAudio();
-                mOffloadAudio = false;
 
                 performSeek(positionUs, false /* needNotify */);
                 if (reason == Renderer::kDueToError) {
+                    mRenderer->signalDisableOffloadAudio();
+                    mOffloadAudio = false;
                     instantiateDecoder(true /* audio */, &mAudioDecoder);
                 }
             }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index ab46074..4bff90f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -316,6 +316,13 @@
 }
 
 status_t NuPlayerDriver::pause() {
+    // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
+    // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
+    // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
+    // getCurrentPosition here.
+    int msec;
+    getCurrentPosition(&msec);
+
     Mutex::Autolock autoLock(mLock);
 
     switch (mState) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 638d9bc..bb6fe41 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -155,6 +155,10 @@
     (new AMessage(kWhatDisableOffloadAudio, id()))->post();
 }
 
+void NuPlayer::Renderer::signalEnableOffloadAudio() {
+    (new AMessage(kWhatEnableOffloadAudio, id()))->post();
+}
+
 void NuPlayer::Renderer::pause() {
     (new AMessage(kWhatPause, id()))->post();
 }
@@ -406,6 +410,12 @@
             break;
         }
 
+        case kWhatEnableOffloadAudio:
+        {
+            onEnableOffloadAudio();
+            break;
+        }
+
         case kWhatPause:
         {
             onPause();
@@ -1012,6 +1022,7 @@
          Mutex::Autolock autoLock(mLock);
          syncQueuesDone_l();
          setPauseStartedTimeRealUs(-1);
+         setAnchorTime(-1, -1);
     }
 
     ALOGV("flushing %s", audio ? "audio" : "video");
@@ -1115,6 +1126,12 @@
     ++mAudioQueueGeneration;
 }
 
+void NuPlayer::Renderer::onEnableOffloadAudio() {
+    Mutex::Autolock autoLock(mLock);
+    mFlags |= FLAG_OFFLOAD_AUDIO;
+    ++mAudioQueueGeneration;
+}
+
 void NuPlayer::Renderer::onPause() {
     if (mPaused) {
         ALOGW("Renderer::onPause() called while already paused!");
@@ -1398,6 +1415,9 @@
     if (audioSinkChanged) {
         onAudioSinkChanged();
     }
+    if (offloadingAudio()) {
+        mAudioOffloadTornDown = false;
+    }
 
     return offloadingAudio();
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index b15a266..dc37b93 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -53,6 +53,7 @@
     void signalAudioSinkChanged();
 
     void signalDisableOffloadAudio();
+    void signalEnableOffloadAudio();
 
     void pause();
     void resume();
@@ -112,6 +113,7 @@
         kWhatCloseAudioSink      = 'clsA',
         kWhatStopAudioSink       = 'stpA',
         kWhatDisableOffloadAudio = 'noOA',
+        kWhatEnableOffloadAudio  = 'enOA',
         kWhatSetVideoFrameRate   = 'sVFR',
     };
 
@@ -195,6 +197,7 @@
     void onFlush(const sp<AMessage> &msg);
     void onAudioSinkChanged();
     void onDisableOffloadAudio();
+    void onEnableOffloadAudio();
     void onPause();
     void onResume();
     void onSetVideoFrameRate(float fps);
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 193f8a7..7bfd2fb 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -68,11 +68,8 @@
         $(TOP)/frameworks/native/include/media/openmax \
         $(TOP)/external/flac/include \
         $(TOP)/external/tremolo \
-        $(TOP)/external/openssl/include \
         $(TOP)/external/libvpx/libwebm \
         $(TOP)/system/netd/include \
-        $(TOP)/external/icu/icu4c/source/common \
-        $(TOP)/external/icu/icu4c/source/i18n \
 
 LOCAL_SHARED_LIBRARIES := \
         libbinder \
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 087f345..64ab2f7 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1533,13 +1533,13 @@
             break;
         }
 
-        // @xyz
-        case FOURCC('\xA9', 'x', 'y', 'z'):
+        // ©xyz
+        case FOURCC(0xA9, 'x', 'y', 'z'):
         {
             *offset += chunk_size;
 
-            // Best case the total data length inside "@xyz" box
-            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
+            // Best case the total data length inside "©xyz" box
+            // would be 8, for instance "©xyz" + "\x00\x04\x15\xc7" + "0+0/",
             // where "\x00\x04" is the text string length with value = 4,
             // "\0x15\xc7" is the language code = en, and "0+0" is a
             // location (string) value with longitude = 0 and latitude = 0.