Merge "aaudio: fix warning for use after free"
diff --git a/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.cpp b/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.cpp
index faea008..4b4051d 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeySessionLibrary.cpp
@@ -95,7 +95,7 @@
 void ClearKeySessionLibrary::destroyPlugin(CasPlugin *plugin) {
     Mutex::Autolock lock(mSessionsLock);
 
-    for (ssize_t index = mIDToSessionMap.size() - 1; index >= 0; index--) {
+    for (ssize_t index = (ssize_t)mIDToSessionMap.size() - 1; index >= 0; index--) {
         sp<ClearKeyCasSession> session = mIDToSessionMap.valueAt(index);
         if (session->getPlugin() == plugin) {
             mIDToSessionMap.removeItemsAt(index);
diff --git a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
index 6e1004c..ee8dba3 100644
--- a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
+++ b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
@@ -36,8 +36,6 @@
 const String8 kCasTypeTag("cas_type");
 const String8 kBase64Padding("=");
 
-const uint32_t kKeyLength = 16;
-
 JsonAssetLoader::JsonAssetLoader() {
 }
 
diff --git a/drm/mediacas/plugins/clearkey/ecm_generator.cpp b/drm/mediacas/plugins/clearkey/ecm_generator.cpp
index 7d29659..218ce35 100644
--- a/drm/mediacas/plugins/clearkey/ecm_generator.cpp
+++ b/drm/mediacas/plugins/clearkey/ecm_generator.cpp
@@ -38,8 +38,6 @@
 const uint16_t kTotalEcmSize =
         kEcmClearFieldsSize + kContentKeyByteSize; // clear fields + clear key
 
-const uint32_t kKeyLength = 16;
-
 #define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32_t *>(_p))
 
 static uint32_t Load32(const void *p) {
diff --git a/drm/mediacas/plugins/clearkey/tests/ClearKeyFetcherTest.cpp b/drm/mediacas/plugins/clearkey/tests/ClearKeyFetcherTest.cpp
index ace086a..d12cfeb 100644
--- a/drm/mediacas/plugins/clearkey/tests/ClearKeyFetcherTest.cpp
+++ b/drm/mediacas/plugins/clearkey/tests/ClearKeyFetcherTest.cpp
@@ -93,7 +93,7 @@
     uint64_t asset_id;
     std::vector<KeyFetcher::KeyInfo> keys;
     EXPECT_EQ(OK, fetcher.ObtainKey(ecm_, &asset_id, &keys));
-    EXPECT_EQ(2, keys.size());
+    EXPECT_EQ(2U, keys.size());
     EXPECT_EQ(0, keys[0].key_id);
     EXPECT_EQ(content_key_[0]->size(), keys[0].key_bytes->size());
     EXPECT_EQ(0, memcmp(content_key_[0]->data(),
diff --git a/drm/mediacas/plugins/mock/MockCasPlugin.cpp b/drm/mediacas/plugins/mock/MockCasPlugin.cpp
index 500208b..06516b5 100644
--- a/drm/mediacas/plugins/mock/MockCasPlugin.cpp
+++ b/drm/mediacas/plugins/mock/MockCasPlugin.cpp
@@ -49,8 +49,8 @@
 
 status_t MockCasFactory::createPlugin(
         int32_t CA_system_id,
-        uint64_t appData,
-        CasPluginCallback callback,
+        uint64_t /*appData*/,
+        CasPluginCallback /*callback*/,
         CasPlugin **plugin) {
     if (!isSystemIdSupported(CA_system_id)) {
         return BAD_VALUE;
@@ -98,7 +98,7 @@
     MockSessionLibrary::get()->destroyPlugin(this);
 }
 
-status_t MockCasPlugin::setPrivateData(const CasData &data) {
+status_t MockCasPlugin::setPrivateData(const CasData& /*data*/) {
     ALOGV("setPrivateData");
     return OK;
 }
@@ -123,7 +123,7 @@
 }
 
 status_t MockCasPlugin::setSessionPrivateData(
-        const CasSessionId &sessionId, const CasData &data) {
+        const CasSessionId &sessionId, const CasData& /*data*/) {
     ALOGV("setSessionPrivateData: sessionId=%s",
             arrayToString(sessionId).string());
     Mutex::Autolock lock(mLock);
@@ -163,7 +163,7 @@
 }
 
 status_t MockCasPlugin::sendEvent(
-        int32_t event, int arg, const CasData &eventData) {
+        int32_t event, int /*arg*/, const CasData& /*eventData*/) {
     ALOGV("sendEvent: event=%d", event);
     Mutex::Autolock lock(mLock);
 
@@ -178,7 +178,7 @@
 }
 
 status_t MockCasPlugin::refreshEntitlements(
-        int32_t refreshType, const CasData &refreshData) {
+        int32_t /*refreshType*/, const CasData &refreshData) {
     ALOGV("refreshEntitlements: refreshData=%s", arrayToString(refreshData).string());
     Mutex::Autolock lock(mLock);
 
@@ -216,7 +216,7 @@
         int32_t srcOffset,
         void *dstPtr,
         int32_t dstOffset,
-        AString *errorDetailMsg) {
+        AString* /*errorDetailMsg*/) {
     ALOGV("MockDescramblerPlugin::descramble(secure=%d, sctrl=%d,"
           "subSamples=%s, srcPtr=%p, dstPtr=%p, srcOffset=%d, dstOffset=%d)",
           (int)secure, (int)scramblingControl,
diff --git a/include/media/AudioClient.h b/include/media/AudioClient.h
index feac9b9..a0530e4 120000
--- a/include/media/AudioClient.h
+++ b/include/media/AudioClient.h
@@ -1 +1 @@
-media/libaudioclient/include/media/AudioClient.h
\ No newline at end of file
+../../media/libaudioclient/include/media/AudioClient.h
\ No newline at end of file
diff --git a/media/extractors/aac/Android.bp b/media/extractors/aac/Android.bp
index 65f9b96..7937a29 100644
--- a/media/extractors/aac/Android.bp
+++ b/media/extractors/aac/Android.bp
@@ -23,6 +23,7 @@
         "-Wall",
         "-fvisibility=hidden",
     ],
+    version_script: "exports.lds",
 
     sanitize: {
         cfi: true,
diff --git a/media/extractors/aac/exports.lds b/media/extractors/aac/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/aac/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/amr/Android.bp b/media/extractors/amr/Android.bp
index 01bbfa2..e5bbe31 100644
--- a/media/extractors/amr/Android.bp
+++ b/media/extractors/amr/Android.bp
@@ -23,6 +23,7 @@
         "-Wall",
         "-fvisibility=hidden",
     ],
+    version_script: "exports.lds",
 
     sanitize: {
         cfi: true,
diff --git a/media/extractors/amr/exports.lds b/media/extractors/amr/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/amr/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 80a4125..84ba6d3 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -28,6 +28,7 @@
         "-Wall",
         "-fvisibility=hidden",
     ],
+    version_script: "exports.lds",
 
     sanitize: {
         cfi: true,
diff --git a/media/extractors/flac/exports.lds b/media/extractors/flac/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/flac/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index 68f8766..9af128e 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -27,6 +27,7 @@
         "-Wall",
         "-fvisibility=hidden",
     ],
+    version_script: "exports.lds",
 
     sanitize: {
         cfi: true,
diff --git a/media/extractors/midi/exports.lds b/media/extractors/midi/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/midi/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index 350c6fe..0301ffa 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -31,6 +31,7 @@
         "-Wall",
         "-fvisibility=hidden",
     ],
+    version_script: "exports.lds",
 
     sanitize: {
         cfi: true,
diff --git a/media/extractors/mkv/exports.lds b/media/extractors/mkv/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/mkv/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/mp3/Android.bp b/media/extractors/mp3/Android.bp
index 6912ef1..d93562c 100644
--- a/media/extractors/mp3/Android.bp
+++ b/media/extractors/mp3/Android.bp
@@ -31,6 +31,7 @@
         "-Wall",
         "-fvisibility=hidden",
     ],
+    version_script: "exports.lds",
 
     sanitize: {
         cfi: true,
diff --git a/media/extractors/mp3/exports.lds b/media/extractors/mp3/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/mp3/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/mp4/Android.bp b/media/extractors/mp4/Android.bp
index 49a3714..fce8dd6 100644
--- a/media/extractors/mp4/Android.bp
+++ b/media/extractors/mp4/Android.bp
@@ -33,6 +33,7 @@
         "-Wall",
         "-fvisibility=hidden",
     ],
+    version_script: "exports.lds",
 
     sanitize: {
         cfi: true,
diff --git a/media/extractors/mp4/exports.lds b/media/extractors/mp4/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/mp4/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index 50f740b..18f9ee4 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -22,7 +22,6 @@
         "liblog",
         "libmedia",  // Needed for IStreamListener
         "libmediaextractor",
-        "libstagefright",  // Needed for AnotherPacketSource and more
         "libstagefright_foundation",
         "libutils",
     ],
@@ -41,6 +40,7 @@
         "-Wall",
         "-fvisibility=hidden",
     ],
+    version_script: "exports.lds",
 
     sanitize: {
         cfi: true,
diff --git a/media/extractors/mpeg2/exports.lds b/media/extractors/mpeg2/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/mpeg2/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp
index 6bd8025..2c09a5f 100644
--- a/media/extractors/ogg/Android.bp
+++ b/media/extractors/ogg/Android.bp
@@ -28,6 +28,7 @@
         "-Wall",
         "-fvisibility=hidden",
     ],
+    version_script: "exports.lds",
 
     sanitize: {
         cfi: true,
diff --git a/media/extractors/ogg/exports.lds b/media/extractors/ogg/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/ogg/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index f310892..65c71ef 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -27,6 +27,7 @@
         "-Wall",
         "-fvisibility=hidden",
     ],
+    version_script: "exports.lds",
 
     sanitize: {
         cfi: true,
diff --git a/media/extractors/wav/exports.lds b/media/extractors/wav/exports.lds
new file mode 100644
index 0000000..b1309ee
--- /dev/null
+++ b/media/extractors/wav/exports.lds
@@ -0,0 +1 @@
+{ global: GETEXTRACTORDEF; local: *; };
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index fc5830a..f709f41 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -291,7 +291,7 @@
     const int32_t maxBytesPerFrame = maxChannels * sizeof(float);
     // Prevent overflow by limiting multiplicands.
     if (bytesPerFrame > maxBytesPerFrame || numFrames > (0x3FFFFFFF / maxBytesPerFrame)) {
-        ALOGE("size overflow, numFrames = %d, frameSize = %zd", numFrames, bytesPerFrame);
+        ALOGE("size overflow, numFrames = %d, frameSize = %d", numFrames, bytesPerFrame);
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
     *sizeInBytes = numFrames * bytesPerFrame;
diff --git a/media/libaaudio/tests/test_various.cpp b/media/libaaudio/tests/test_various.cpp
index de386da..dc19985 100644
--- a/media/libaaudio/tests/test_various.cpp
+++ b/media/libaaudio/tests/test_various.cpp
@@ -16,17 +16,19 @@
 
 // Test various AAudio features including AAudioStream_setBufferSizeInFrames().
 
+#include <condition_variable>
+#include <mutex>
 #include <stdio.h>
-//#include <stdlib.h>
-//#include <math.h>
 
 #include <android-base/macros.h>
 #include <aaudio/AAudio.h>
 
 #include <gtest/gtest.h>
+#include <unistd.h>
+
 
 // Callback function that does nothing.
-aaudio_data_callback_result_t MyDataCallbackProc(
+aaudio_data_callback_result_t NoopDataCallbackProc(
         AAudioStream *stream,
         void *userData,
         void *audioData,
@@ -52,7 +54,7 @@
     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
 
 // Request stream properties.
-    AAudioStreamBuilder_setDataCallback(aaudioBuilder, MyDataCallbackProc, nullptr);
+    AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
 
 // Create an AAudioStream using the Builder.
@@ -85,7 +87,7 @@
     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
 
 // Request stream properties.
-    AAudioStreamBuilder_setDataCallback(aaudioBuilder, MyDataCallbackProc, nullptr);
+    AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
 
 // Create an AAudioStream using the Builder.
@@ -111,6 +113,7 @@
 
 //int main() { // To fix Android Studio formatting when editing.
 TEST(test_various, aaudio_set_buffer_size) {
+
     int32_t bufferCapacity;
     int32_t framesPerBurst = 0;
     int32_t actualSize = 0;
@@ -122,7 +125,7 @@
     ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
 
     // Request stream properties.
-    AAudioStreamBuilder_setDataCallback(aaudioBuilder, MyDataCallbackProc, nullptr);
+    AAudioStreamBuilder_setDataCallback(aaudioBuilder, NoopDataCallbackProc, nullptr);
     AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
 
     // Create an AAudioStream using the Builder.
@@ -170,3 +173,155 @@
     AAudioStream_close(aaudioStream);
     AAudioStreamBuilder_delete(aaudioBuilder);
 }
+
+
+// ************************************************************
+// Test to make sure that AAUDIO_CALLBACK_RESULT_STOP works.
+
+// Callback function that counts calls.
+aaudio_data_callback_result_t CallbackOnceProc(
+        AAudioStream *stream,
+        void *userData,
+        void *audioData,
+        int32_t numFrames
+) {
+    (void) stream;
+    (void) audioData;
+    (void) numFrames;
+
+    std::atomic<int32_t> *callbackCountPtr = (std::atomic<int32_t> *)userData;
+    (*callbackCountPtr)++;
+
+    return AAUDIO_CALLBACK_RESULT_STOP;
+}
+
+void checkCallbackOnce(aaudio_performance_mode_t perfMode) {
+
+    std::atomic<int32_t>   callbackCount{0};
+
+    AAudioStreamBuilder *aaudioBuilder = nullptr;
+    AAudioStream *aaudioStream = nullptr;
+
+    // Use an AAudioStreamBuilder to contain requested parameters.
+    ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
+
+    // Request stream properties.
+    AAudioStreamBuilder_setDataCallback(aaudioBuilder, CallbackOnceProc, &callbackCount);
+    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
+
+    // Create an AAudioStream using the Builder.
+    ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+    AAudioStreamBuilder_delete(aaudioBuilder);
+
+    ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
+
+    sleep(1); // Give callback a chance to run many times.
+
+    EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
+
+    EXPECT_EQ(1, callbackCount.load()); // should stop after first call
+
+    EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
+}
+
+TEST(test_various, aaudio_callback_once_none) {
+    checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_NONE);
+}
+
+TEST(test_various, aaudio_callback_once_lowlat) {
+    checkCallbackOnce(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+}
+
+// ************************************************************
+struct WakeUpCallbackData {
+    void wakeOther() {
+        // signal waiting test to wake up
+        {
+            std::lock_guard <std::mutex> lock(mutex);
+            finished = true;
+        }
+        conditionVariable.notify_one();
+    }
+
+    void waitForFinished() {
+        std::unique_lock <std::mutex> aLock(mutex);
+        conditionVariable.wait(aLock, [=] { return finished; });
+    }
+
+    // For signalling foreground test when callback finished
+    std::mutex              mutex;
+    std::condition_variable conditionVariable;
+    bool                    finished = false;
+};
+
+// Test to make sure we cannot call recursively into the system from a callback.
+struct DangerousData : public WakeUpCallbackData {
+    aaudio_result_t resultStart = AAUDIO_OK;
+    aaudio_result_t resultStop = AAUDIO_OK;
+    aaudio_result_t resultPause = AAUDIO_OK;
+    aaudio_result_t resultFlush = AAUDIO_OK;
+    aaudio_result_t resultClose = AAUDIO_OK;
+};
+
+// Callback function that tries to call back into the stream.
+aaudio_data_callback_result_t DangerousDataCallbackProc(
+        AAudioStream *stream,
+        void *userData,
+        void *audioData,
+        int32_t numFrames) {
+    (void) audioData;
+    (void) numFrames;
+
+    DangerousData *data = (DangerousData *)userData;
+    data->resultStart = AAudioStream_requestStart(stream);
+    data->resultStop = AAudioStream_requestStop(stream);
+    data->resultPause = AAudioStream_requestPause(stream);
+    data->resultFlush = AAudioStream_requestFlush(stream);
+    data->resultClose = AAudioStream_close(stream);
+
+    data->wakeOther();
+
+    return AAUDIO_CALLBACK_RESULT_STOP;
+}
+
+//int main() { // To fix Android Studio formatting when editing.
+void checkDangerousCallback(aaudio_performance_mode_t perfMode) {
+    DangerousData        dangerousData;
+    AAudioStreamBuilder *aaudioBuilder = nullptr;
+    AAudioStream        *aaudioStream = nullptr;
+
+    // Use an AAudioStreamBuilder to contain requested parameters.
+    ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
+
+    // Request stream properties.
+    AAudioStreamBuilder_setDataCallback(aaudioBuilder, DangerousDataCallbackProc, &dangerousData);
+    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
+
+    // Create an AAudioStream using the Builder.
+    ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
+    AAudioStreamBuilder_delete(aaudioBuilder);
+
+    ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream));
+
+    dangerousData.waitForFinished();
+
+    EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
+
+    EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStart);
+    EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultStop);
+    EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultPause);
+    EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultFlush);
+    EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE, dangerousData.resultClose);
+
+    EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
+}
+
+//int main() { // To fix Android Studio formatting when editing.
+
+TEST(test_various, aaudio_callback_blockers_none) {
+    checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_NONE);
+}
+
+TEST(test_various, aaudio_callback_blockers_lowlat) {
+    checkDangerousCallback(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+}
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 95e95de..d18f611 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -180,7 +180,6 @@
     ],
 
     shared_libs: [
-        "libui",
         "liblog",
         "libcutils",
         "libutils",
@@ -196,8 +195,6 @@
         "libdl",
         "libaudioutils",
         "libaudioclient",
-        "libhidlbase",
-        "libhidltransport",
         "libmedia_omx",
     ],
 
diff --git a/media/libmedia/MediaPlayer2Factory.cpp b/media/libmedia/MediaPlayer2Factory.cpp
index ca7b96f..d6aab70 100644
--- a/media/libmedia/MediaPlayer2Factory.cpp
+++ b/media/libmedia/MediaPlayer2Factory.cpp
@@ -126,8 +126,8 @@
 
 sp<MediaPlayer2Base> MediaPlayer2Factory::createPlayer(
         player2_type playerType,
-        void* cookie,
-        notify_callback_f notifyFunc,
+        const wp<MediaPlayer2Engine> &client,
+        MediaPlayer2Base::NotifyCallback notifyFunc,
         pid_t pid) {
     sp<MediaPlayer2Base> p;
     IFactory* factory;
@@ -152,7 +152,7 @@
 
     init_result = p->initCheck();
     if (init_result == NO_ERROR) {
-        p->setNotifyCallback(cookie, notifyFunc);
+        p->setNotifyCallback(client, notifyFunc);
     } else {
         ALOGE("Failed to create player object of type %d, initCheck failed"
               " (res = %d)", playerType, init_result);
diff --git a/media/libmedia/MediaPlayer2Factory.h b/media/libmedia/MediaPlayer2Factory.h
index 5813b2e..799b5f3 100644
--- a/media/libmedia/MediaPlayer2Factory.h
+++ b/media/libmedia/MediaPlayer2Factory.h
@@ -65,8 +65,8 @@
                                       const sp<DataSource> &source);
 
     static sp<MediaPlayer2Base> createPlayer(player2_type playerType,
-                                             void* cookie,
-                                             notify_callback_f notifyFunc,
+                                             const wp<MediaPlayer2Engine> &client,
+                                             MediaPlayer2Base::NotifyCallback notifyFunc,
                                              pid_t pid);
 
     static void registerBuiltinFactories();
diff --git a/media/libmedia/MediaPlayer2Manager.cpp b/media/libmedia/MediaPlayer2Manager.cpp
index 9b7f98a..637214e 100644
--- a/media/libmedia/MediaPlayer2Manager.cpp
+++ b/media/libmedia/MediaPlayer2Manager.cpp
@@ -1258,12 +1258,13 @@
 }
 
 void MediaPlayer2Manager::Client::notify(
-        void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
+        const wp<MediaPlayer2Engine> &listener, int msg, int ext1, int ext2, const Parcel *obj)
 {
-    Client* client = static_cast<Client*>(cookie);
-    if (client == NULL) {
+    sp<MediaPlayer2Engine> spListener = listener.promote();
+    if (spListener == NULL) {
         return;
     }
+    Client* client = static_cast<Client*>(spListener.get());
 
     sp<MediaPlayer2EngineClient> c;
     sp<Client> nextClient;
@@ -1311,7 +1312,7 @@
     }
 
     if (c != NULL) {
-        ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
+        ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, spListener.get(), msg, ext1, ext2);
         c->notify(msg, ext1, ext2, obj);
     }
 }
@@ -1405,7 +1406,9 @@
 #if CALLBACK_ANTAGONIZER
 const int Antagonizer::interval = 10000; // 10 msecs
 
-Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
+Antagonizer::Antagonizer(
+        MediaPlayer2Manager::NotifyCallback cb,
+        const wp<MediaPlayer2Engine> &client) :
     mExit(false), mActive(false), mClient(client), mCb(cb)
 {
     createThread(callbackThread, this);
diff --git a/media/libmedia/MediaPlayer2Manager.h b/media/libmedia/MediaPlayer2Manager.h
index b346f40..8f0c491 100644
--- a/media/libmedia/MediaPlayer2Manager.h
+++ b/media/libmedia/MediaPlayer2Manager.h
@@ -46,20 +46,22 @@
 #if CALLBACK_ANTAGONIZER
 class Antagonizer {
 public:
-    Antagonizer(notify_callback_f cb, void* client);
+    Antagonizer(
+            MediaPlayer2Base::NotifyCallback cb,
+            const wp<MediaPlayer2Engine> &client);
     void start() { mActive = true; }
     void stop() { mActive = false; }
     void kill();
 private:
     static const int interval;
     Antagonizer();
-    static int callbackThread(void* cookie);
-    Mutex               mLock;
-    Condition           mCondition;
-    bool                mExit;
-    bool                mActive;
-    void*               mClient;
-    notify_callback_f   mCb;
+    static int callbackThread(void *cookie);
+    Mutex                            mLock;
+    Condition                        mCondition;
+    bool                             mExit;
+    bool                             mActive;
+    wp<MediaPlayer2Engine>           mClient;
+    MediaPlayer2Base::NotifyCallback mCb;
 };
 #endif
 
@@ -301,7 +303,7 @@
         status_t                setDataSource_post(const sp<MediaPlayer2Base>& p,
                                                    status_t status);
 
-        static  void            notify(void* cookie, int msg,
+        static  void            notify(const wp<MediaPlayer2Engine> &listener, int msg,
                                        int ext1, int ext2, const Parcel *obj);
 
                 pid_t           pid() const { return mPid; }
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..7c8e3e6 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::
@@ -67,14 +68,14 @@
 // duration below which we do not allow deep audio buffering
 #define AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US 5000000
 
-// callback mechanism for passing messages to MediaPlayer2 object
-typedef void (*notify_callback_f)(void* cookie,
-        int msg, int ext1, int ext2, const Parcel *obj);
-
 // abstract base class - use MediaPlayer2Interface
-class MediaPlayer2Base : public RefBase
+class MediaPlayer2Base : public AHandler
 {
 public:
+    // callback mechanism for passing messages to MediaPlayer2 object
+    typedef void (*NotifyCallback)(const wp<MediaPlayer2Engine> &listener,
+            int msg, int ext1, int ext2, const Parcel *obj);
+
     // AudioSink: abstraction layer for audio output
     class AudioSink : public RefBase {
     public:
@@ -158,7 +159,7 @@
         virtual status_t    enableAudioDeviceCallback(bool enabled);
     };
 
-                        MediaPlayer2Base() : mCookie(0), mNotify(0) {}
+                        MediaPlayer2Base() : mClient(0), mNotify(0) {}
     virtual             ~MediaPlayer2Base() {}
     virtual status_t    initCheck() = 0;
     virtual bool        hardwareOutput() = 0;
@@ -272,28 +273,30 @@
     };
 
     void        setNotifyCallback(
-            void* cookie, notify_callback_f notifyFunc) {
+            const wp<MediaPlayer2Engine> &client, NotifyCallback notifyFunc) {
         Mutex::Autolock autoLock(mNotifyLock);
-        mCookie = cookie; mNotify = notifyFunc;
+        mClient = client; mNotify = notifyFunc;
     }
 
     void        sendEvent(int msg, int ext1=0, int ext2=0,
                           const Parcel *obj=NULL) {
-        notify_callback_f notifyCB;
-        void* cookie;
+        NotifyCallback notifyCB;
+        wp<MediaPlayer2Engine> client;
         {
             Mutex::Autolock autoLock(mNotifyLock);
             notifyCB = mNotify;
-            cookie = mCookie;
+            client = mClient;
         }
 
-        if (notifyCB) notifyCB(cookie, msg, ext1, ext2, obj);
+        if (notifyCB) notifyCB(client, msg, ext1, ext2, obj);
     }
 
     virtual status_t dump(int /* fd */, const Vector<String16>& /* args */) const {
         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;
@@ -305,9 +308,9 @@
 private:
     friend class MediaPlayer2Manager;
 
-    Mutex               mNotifyLock;
-    void*               mCookie;
-    notify_callback_f   mNotify;
+    Mutex                  mNotifyLock;
+    wp<MediaPlayer2Engine> mClient;
+    NotifyCallback         mNotify;
 };
 
 // Implement this class for media players that use the AudioFlinger software mixer
diff --git a/media/libmedia/nuplayer2/GenericSource.cpp b/media/libmedia/nuplayer2/GenericSource.cpp
index 900c78b..6f78b6b 100644
--- a/media/libmedia/nuplayer2/GenericSource.cpp
+++ b/media/libmedia/nuplayer2/GenericSource.cpp
@@ -162,15 +162,30 @@
 
 status_t NuPlayer2::GenericSource::initFromDataSource() {
     sp<IMediaExtractor> extractor;
-    CHECK(mDataSource != NULL);
+    CHECK(mDataSource != NULL || mFd != -1);
     sp<DataSource> dataSource = mDataSource;
+    const int fd = mFd;
+    const int64_t offset = mOffset;
+    const int64_t length = mLength;
 
     mLock.unlock();
     // This might take long time if data source is not reliable.
-    extractor = MediaExtractorFactory::Create(dataSource, NULL);
+    if (dataSource != nullptr) {
+        extractor = MediaExtractorFactory::Create(dataSource, NULL /* mime */);
+    } else {
+        extractor = MediaExtractorFactory::CreateFromFd(
+                fd, offset, length, NULL /* mime */, &dataSource);
+    }
+
+    if (dataSource == nullptr) {
+        ALOGE("initFromDataSource, failed to create data source!");
+        mLock.lock();
+        return UNKNOWN_ERROR;
+    }
 
     if (extractor == NULL) {
         ALOGE("initFromDataSource, cannot create extractor!");
+        mLock.lock();
         return UNKNOWN_ERROR;
     }
 
@@ -179,10 +194,13 @@
     size_t numtracks = extractor->countTracks();
     if (numtracks == 0) {
         ALOGE("initFromDataSource, source has no track!");
+        mLock.lock();
         return UNKNOWN_ERROR;
     }
 
     mLock.lock();
+    mFd = -1;
+    mDataSource = dataSource;
     mFileMeta = fileMeta;
     if (mFileMeta != NULL) {
         int64_t duration;
@@ -395,51 +413,16 @@
             if (!mDisconnected) {
                 mDataSource = dataSource;
             }
-        } else {
-            if (property_get_bool("media.stagefright.extractremote", true) &&
-                    !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
-                sp<IBinder> binder =
-                        defaultServiceManager()->getService(String16("media.extractor"));
-                if (binder != nullptr) {
-                    ALOGD("FileSource remote");
-                    sp<IMediaExtractorService> mediaExService(
-                            interface_cast<IMediaExtractorService>(binder));
-                    sp<IDataSource> source =
-                            mediaExService->makeIDataSource(mFd, mOffset, mLength);
-                    ALOGV("IDataSource(FileSource): %p %d %lld %lld",
-                            source.get(), mFd, (long long)mOffset, (long long)mLength);
-                    if (source.get() != nullptr) {
-                        mDataSource = CreateDataSourceFromIDataSource(source);
-                        if (mDataSource != nullptr) {
-                            // Close the local file descriptor as it is not needed anymore.
-                            close(mFd);
-                            mFd = -1;
-                        }
-                    } else {
-                        ALOGW("extractor service cannot make data source");
-                    }
-                } else {
-                    ALOGW("extractor service not running");
-                }
-            }
-            if (mDataSource == nullptr) {
-                ALOGD("FileSource local");
-                mDataSource = new FileSource(mFd, mOffset, mLength);
-            }
-            // TODO: close should always be done on mFd, see the lines following
-            // CreateDataSourceFromIDataSource above,
-            // and the FileSource constructor should dup the mFd argument as needed.
-            mFd = -1;
         }
 
-        if (mDataSource == NULL) {
+        if (mFd == -1 && mDataSource == NULL) {
             ALOGE("Failed to create data source!");
             notifyPreparedAndCleanup(UNKNOWN_ERROR);
             return;
         }
     }
 
-    if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
+    if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
         mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
     }
 
diff --git a/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp b/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp
index 18207b0..d78a8e8 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp
@@ -766,6 +766,8 @@
         reply->setInt32("eos", true);
     }
 
+    mNumFramesTotal += !mIsAudio;
+
     if (mSkipRenderingUntilMediaTimeUs >= 0) {
         if (timeUs < mSkipRenderingUntilMediaTimeUs) {
             ALOGV("[%s] dropping buffer at time %lld as requested.",
@@ -784,8 +786,6 @@
         mSkipRenderingUntilMediaTimeUs = -1;
     }
 
-    mNumFramesTotal += !mIsAudio;
-
     // wait until 1st frame comes out to signal resume complete
     notifyResumeCompleteIfNecessary();
 
diff --git a/media/libmedia/nuplayer2/NuPlayer2Driver.cpp b/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
index c0f0bad..dd0da8a 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";
@@ -55,6 +55,7 @@
 static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
 static const char *kPlayerError = "android.media.mediaplayer.err";
 static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
+static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
 static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
 //
 static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
@@ -75,6 +76,7 @@
       mRebufferingEvents(0),
       mRebufferingAtExit(false),
       mLooper(new ALooper),
+      mNuPlayer2Looper(new ALooper),
       mMediaClock(new MediaClock),
       mPlayer(new NuPlayer2(pid, mMediaClock)),
       mPlayerFlags(0),
@@ -85,6 +87,7 @@
       mAutoLoop(false) {
     ALOGD("NuPlayer2Driver(%p) created, clientPid(%d)", this, pid);
     mLooper->setName("NuPlayer2Driver Looper");
+    mNuPlayer2Looper->setName("NuPlayer2 Looper");
 
     mMediaClock->init();
 
@@ -92,18 +95,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 +121,12 @@
 }
 
 status_t NuPlayer2Driver::initCheck() {
+    mLooper->start(
+            false, /* runOnCallingThread */
+            true,  /* canCallJava */
+            PRIORITY_AUDIO);
+
+    mLooper->registerHandler(this);
     return OK;
 }
 
@@ -381,7 +391,7 @@
 
         case STATE_PAUSED:
             mState = STATE_STOPPED;
-            notifyListener_l(MEDIA2_STOPPED);
+            sendNotifyOnLooper(MEDIA2_STOPPED);
             break;
 
         case STATE_PREPARED:
@@ -416,7 +426,7 @@
 
         case STATE_RUNNING:
             mState = STATE_PAUSED;
-            notifyListener_l(MEDIA2_PAUSED);
+            sendNotifyOnLooper(MEDIA2_PAUSED);
             mPlayer->pause();
             break;
 
@@ -440,7 +450,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 +488,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 +661,7 @@
         {
             CHECK(mIsAsyncPrepare);
 
-            notifyListener_l(MEDIA2_PREPARED);
+            sendNotifyOnLooper(MEDIA2_PREPARED);
             break;
         }
 
@@ -660,7 +670,7 @@
     }
 
     if (mState != STATE_STOPPED) {
-        notifyListener_l(MEDIA2_STOPPED);
+        sendNotifyOnLooper(MEDIA2_STOPPED);
     }
 
     mState = STATE_RESET_IN_PROGRESS;
@@ -704,7 +714,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 +949,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);
@@ -993,6 +1016,7 @@
                 if (ext2 != 0) {
                     mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
                 }
+                mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
             }
             mAtEOS = true;
             break;
@@ -1007,6 +1031,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);
 
@@ -1089,4 +1119,30 @@
     return ret;
 }
 
+std::string NuPlayer2Driver::stateString(State state) {
+    const char *rval = NULL;
+    char rawbuffer[16];  // allows "%d"
+
+    switch (state) {
+        case STATE_IDLE: rval = "IDLE"; break;
+        case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
+        case STATE_UNPREPARED: rval = "UNPREPARED"; break;
+        case STATE_PREPARING: rval = "PREPARING"; break;
+        case STATE_PREPARED: rval = "PREPARED"; break;
+        case STATE_RUNNING: rval = "RUNNING"; break;
+        case STATE_PAUSED: rval = "PAUSED"; break;
+        case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
+        case STATE_STOPPED: rval = "STOPPED"; break;
+        case STATE_STOPPED_AND_PREPARING: rval = "STOPPED_AND_PREPARING"; break;
+        case STATE_STOPPED_AND_PREPARED: rval = "STOPPED_AND_PREPARED"; break;
+        default:
+            // yes, this buffer is shared and vulnerable to races
+            snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
+            rval = rawbuffer;
+            break;
+    }
+
+    return rval;
+}
+
 }  // namespace android
diff --git a/media/libmedia/nuplayer2/NuPlayer2Driver.h b/media/libmedia/nuplayer2/NuPlayer2Driver.h
index edd4556..0028d05 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,12 @@
         STATE_STOPPED_AND_PREPARED,     // equivalent to PAUSED, but seek complete
     };
 
+    std::string stateString(State state);
+
+    enum {
+        kWhatNotifyListener,
+    };
+
     mutable Mutex mLock;
     Condition mCondition;
 
@@ -134,6 +142,7 @@
     // <<<
 
     sp<ALooper> mLooper;
+    sp<ALooper> mNuPlayer2Looper;
     const sp<MediaClock> mMediaClock;
     const sp<NuPlayer2> mPlayer;
     sp<AudioSink> mAudioSink;
@@ -146,13 +155,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);
 };
diff --git a/media/libmediaextractor/DataSource.cpp b/media/libmediaextractor/DataSource.cpp
index c22e4cb..72959c6 100644
--- a/media/libmediaextractor/DataSource.cpp
+++ b/media/libmediaextractor/DataSource.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "DataSource"
 
 #include <media/DataSource.h>
-#include <media/IDataSource.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/String8.h>
@@ -124,10 +123,6 @@
     return ERROR_UNSUPPORTED;
 }
 
-sp<IDataSource> DataSource::getIDataSource() const {
-    return nullptr;
-}
-
 String8 DataSource::getMIMEType() const {
     return String8("application/octet-stream");
 }
diff --git a/media/libmediaextractor/include/media/DataSource.h b/media/libmediaextractor/include/media/DataSource.h
index e917f4e..0b4bc27 100644
--- a/media/libmediaextractor/include/media/DataSource.h
+++ b/media/libmediaextractor/include/media/DataSource.h
@@ -112,9 +112,6 @@
 
     virtual void close() {};
 
-    // returns a pointer to IDataSource if it is wrapped.
-    virtual sp<IDataSource> getIDataSource() const;
-
 protected:
     virtual ~DataSource() {}
 
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index 055d5ab..3209c6d 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -126,7 +126,7 @@
 
 sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
         player_type playerType,
-        void* cookie,
+        const wp<IMediaPlayer> &client,
         notify_callback_f notifyFunc,
         pid_t pid) {
     sp<MediaPlayerBase> p;
@@ -152,7 +152,7 @@
 
     init_result = p->initCheck();
     if (init_result == NO_ERROR) {
-        p->setNotifyCallback(cookie, notifyFunc);
+        p->setNotifyCallback(client, notifyFunc);
     } else {
         ALOGE("Failed to create player object of type %d, initCheck failed"
               " (res = %d)", playerType, init_result);
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.h b/media/libmediaplayerservice/MediaPlayerFactory.h
index e22a56f..6aedeb2 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.h
+++ b/media/libmediaplayerservice/MediaPlayerFactory.h
@@ -65,7 +65,7 @@
                                      const sp<DataSource> &source);
 
     static sp<MediaPlayerBase> createPlayer(player_type playerType,
-                                            void* cookie,
+                                            const wp<IMediaPlayer> &client,
                                             notify_callback_f notifyFunc,
                                             pid_t pid);
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 495c418..88221ed 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -1421,12 +1421,13 @@
 }
 
 void MediaPlayerService::Client::notify(
-        void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
+        const wp<IMediaPlayer> &listener, int msg, int ext1, int ext2, const Parcel *obj)
 {
-    Client* client = static_cast<Client*>(cookie);
-    if (client == NULL) {
+    sp<IMediaPlayer> spListener = listener.promote();
+    if (spListener == NULL) {
         return;
     }
+    Client* client = static_cast<Client*>(spListener.get());
 
     sp<IMediaPlayerClient> c;
     sp<Client> nextClient;
@@ -1474,7 +1475,7 @@
     }
 
     if (c != NULL) {
-        ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
+        ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, spListener.get(), msg, ext1, ext2);
         c->notify(msg, ext1, ext2, obj);
     }
 }
@@ -1568,7 +1569,7 @@
 #if CALLBACK_ANTAGONIZER
 const int Antagonizer::interval = 10000; // 10 msecs
 
-Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
+Antagonizer::Antagonizer(notify_callback_f cb, const wp<IMediaPlayer> &client) :
     mExit(false), mActive(false), mClient(client), mCb(cb)
 {
     createThread(callbackThread, this);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index eefdd7d..58efa8c 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -51,7 +51,7 @@
 #if CALLBACK_ANTAGONIZER
 class Antagonizer {
 public:
-    Antagonizer(notify_callback_f cb, void* client);
+    Antagonizer(notify_callback_f cb, const wp<IMediaPlayer> &client);
     void start() { mActive = true; }
     void stop() { mActive = false; }
     void kill();
@@ -63,7 +63,7 @@
     Condition           mCondition;
     bool                mExit;
     bool                mActive;
-    void*               mClient;
+    wp<IMediaPlayer>    mClient;
     notify_callback_f   mCb;
 };
 #endif
@@ -377,7 +377,7 @@
         status_t                setDataSource_post(const sp<MediaPlayerBase>& p,
                                                    status_t status);
 
-        static  void            notify(void* cookie, int msg,
+        static  void            notify(const wp<IMediaPlayer> &cookie, int msg,
                                        int ext1, int ext2, const Parcel *obj);
 
                 pid_t           pid() const { return mPid; }
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index a03884f..4b33e61 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -67,7 +67,7 @@
 #define AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US 5000000
 
 // callback mechanism for passing messages to MediaPlayer object
-typedef void (*notify_callback_f)(void* cookie,
+typedef void (*notify_callback_f)(const wp<IMediaPlayer> &listener,
         int msg, int ext1, int ext2, const Parcel *obj);
 
 // abstract base class - use MediaPlayerInterface
@@ -157,7 +157,7 @@
         virtual status_t    enableAudioDeviceCallback(bool enabled);
     };
 
-                        MediaPlayerBase() : mCookie(0), mNotify(0) {}
+                        MediaPlayerBase() : mClient(0), mNotify(0) {}
     virtual             ~MediaPlayerBase() {}
     virtual status_t    initCheck() = 0;
     virtual bool        hardwareOutput() = 0;
@@ -271,22 +271,22 @@
     };
 
     void        setNotifyCallback(
-            void* cookie, notify_callback_f notifyFunc) {
+            const wp<IMediaPlayer> &client, notify_callback_f notifyFunc) {
         Mutex::Autolock autoLock(mNotifyLock);
-        mCookie = cookie; mNotify = notifyFunc;
+        mClient = client; mNotify = notifyFunc;
     }
 
     void        sendEvent(int msg, int ext1=0, int ext2=0,
                           const Parcel *obj=NULL) {
         notify_callback_f notifyCB;
-        void* cookie;
+        wp<IMediaPlayer> client;
         {
             Mutex::Autolock autoLock(mNotifyLock);
             notifyCB = mNotify;
-            cookie = mCookie;
+            client = mClient;
         }
 
-        if (notifyCB) notifyCB(cookie, msg, ext1, ext2, obj);
+        if (notifyCB) notifyCB(client, msg, ext1, ext2, obj);
     }
 
     virtual status_t dump(int /* fd */, const Vector<String16>& /* args */) const {
@@ -305,7 +305,7 @@
     friend class MediaPlayerService;
 
     Mutex               mNotifyLock;
-    void*               mCookie;
+    wp<IMediaPlayer>    mClient;
     notify_callback_f   mNotify;
 };
 
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index a3f4efb..cbbf34d 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -26,7 +26,6 @@
 #include <media/DataSource.h>
 #include <media/MediaExtractor.h>
 #include <media/MediaSource.h>
-#include <media/IMediaExtractorService.h>
 #include <media/IMediaHTTPService.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -161,15 +160,30 @@
 
 status_t NuPlayer::GenericSource::initFromDataSource() {
     sp<IMediaExtractor> extractor;
-    CHECK(mDataSource != NULL);
+    CHECK(mDataSource != NULL || mFd != -1);
     sp<DataSource> dataSource = mDataSource;
+    const int fd = mFd;
+    const int64_t offset = mOffset;
+    const int64_t length = mLength;
 
     mLock.unlock();
     // This might take long time if data source is not reliable.
-    extractor = MediaExtractorFactory::Create(dataSource, NULL);
+    if (dataSource != nullptr) {
+        extractor = MediaExtractorFactory::Create(dataSource, NULL /* mime */);
+    } else {
+        extractor = MediaExtractorFactory::CreateFromFd(
+                fd, offset, length, NULL /* mime */, &dataSource);
+    }
+
+    if (dataSource == nullptr) {
+        ALOGE("initFromDataSource, failed to create data source!");
+        mLock.lock();
+        return UNKNOWN_ERROR;
+    }
 
     if (extractor == NULL) {
         ALOGE("initFromDataSource, cannot create extractor!");
+        mLock.lock();
         return UNKNOWN_ERROR;
     }
 
@@ -178,10 +192,13 @@
     size_t numtracks = extractor->countTracks();
     if (numtracks == 0) {
         ALOGE("initFromDataSource, source has no track!");
+        mLock.lock();
         return UNKNOWN_ERROR;
     }
 
     mLock.lock();
+    mFd = -1;
+    mDataSource = dataSource;
     mFileMeta = fileMeta;
     if (mFileMeta != NULL) {
         int64_t duration;
@@ -394,51 +411,15 @@
             if (!mDisconnected) {
                 mDataSource = dataSource;
             }
-        } else {
-            if (property_get_bool("media.stagefright.extractremote", true) &&
-                    !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
-                sp<IBinder> binder =
-                        defaultServiceManager()->getService(String16("media.extractor"));
-                if (binder != nullptr) {
-                    ALOGD("FileSource remote");
-                    sp<IMediaExtractorService> mediaExService(
-                            interface_cast<IMediaExtractorService>(binder));
-                    sp<IDataSource> source =
-                            mediaExService->makeIDataSource(mFd, mOffset, mLength);
-                    ALOGV("IDataSource(FileSource): %p %d %lld %lld",
-                            source.get(), mFd, (long long)mOffset, (long long)mLength);
-                    if (source.get() != nullptr) {
-                        mDataSource = CreateDataSourceFromIDataSource(source);
-                        if (mDataSource != nullptr) {
-                            // Close the local file descriptor as it is not needed anymore.
-                            close(mFd);
-                            mFd = -1;
-                        }
-                    } else {
-                        ALOGW("extractor service cannot make data source");
-                    }
-                } else {
-                    ALOGW("extractor service not running");
-                }
-            }
-            if (mDataSource == nullptr) {
-                ALOGD("FileSource local");
-                mDataSource = new FileSource(mFd, mOffset, mLength);
-            }
-            // TODO: close should always be done on mFd, see the lines following
-            // CreateDataSourceFromIDataSource above,
-            // and the FileSource constructor should dup the mFd argument as needed.
-            mFd = -1;
         }
-
-        if (mDataSource == NULL) {
+        if (mFd == -1 && mDataSource == NULL) {
             ALOGE("Failed to create data source!");
             notifyPreparedAndCleanup(UNKNOWN_ERROR);
             return;
         }
     }
 
-    if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
+    if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
         mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
     }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index a84d0e5..1b02adb 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -752,6 +752,8 @@
         reply->setInt32("eos", true);
     }
 
+    mNumFramesTotal += !mIsAudio;
+
     if (mSkipRenderingUntilMediaTimeUs >= 0) {
         if (timeUs < mSkipRenderingUntilMediaTimeUs) {
             ALOGV("[%s] dropping buffer at time %lld as requested.",
@@ -770,8 +772,6 @@
         mSkipRenderingUntilMediaTimeUs = -1;
     }
 
-    mNumFramesTotal += !mIsAudio;
-
     // wait until 1st frame comes out to signal resume complete
     notifyResumeCompleteIfNecessary();
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index ebf57c6..8aa06fc 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -55,6 +55,7 @@
 static const char *kPlayerPlaying = "android.media.mediaplayer.playingMs";
 static const char *kPlayerError = "android.media.mediaplayer.err";
 static const char *kPlayerErrorCode = "android.media.mediaplayer.errcode";
+static const char *kPlayerErrorState = "android.media.mediaplayer.errstate";
 static const char *kPlayerDataSourceType = "android.media.mediaplayer.dataSource";
 //
 static const char *kPlayerRebuffering = "android.media.mediaplayer.rebufferingMs";
@@ -993,6 +994,7 @@
                 if (ext2 != 0) {
                     mAnalyticsItem->setInt32(kPlayerErrorCode, ext2);
                 }
+                mAnalyticsItem->setCString(kPlayerErrorState, stateString(mState).c_str());
             }
             mAtEOS = true;
             break;
@@ -1089,4 +1091,30 @@
     return ret;
 }
 
+std::string NuPlayerDriver::stateString(State state) {
+    const char *rval = NULL;
+    char rawbuffer[16];  // allows "%d"
+
+    switch (state) {
+        case STATE_IDLE: rval = "IDLE"; break;
+        case STATE_SET_DATASOURCE_PENDING: rval = "SET_DATASOURCE_PENDING"; break;
+        case STATE_UNPREPARED: rval = "UNPREPARED"; break;
+        case STATE_PREPARING: rval = "PREPARING"; break;
+        case STATE_PREPARED: rval = "PREPARED"; break;
+        case STATE_RUNNING: rval = "RUNNING"; break;
+        case STATE_PAUSED: rval = "PAUSED"; break;
+        case STATE_RESET_IN_PROGRESS: rval = "RESET_IN_PROGRESS"; break;
+        case STATE_STOPPED: rval = "STOPPED"; break;
+        case STATE_STOPPED_AND_PREPARING: rval = "STOPPED_AND_PREPARING"; break;
+        case STATE_STOPPED_AND_PREPARED: rval = "STOPPED_AND_PREPARED"; break;
+        default:
+            // yes, this buffer is shared and vulnerable to races
+            snprintf(rawbuffer, sizeof(rawbuffer), "%d", state);
+            rval = rawbuffer;
+            break;
+    }
+
+    return rval;
+}
+
 }  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 13b46c3..ad878f8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -113,6 +113,8 @@
         STATE_STOPPED_AND_PREPARED,     // equivalent to PAUSED, but seek complete
     };
 
+    std::string stateString(State state);
+
     mutable Mutex mLock;
     Condition mCondition;
 
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index 6dfe2de..f479644 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -113,10 +113,6 @@
     return mIDataSource->DrmInitialization(mime);
 }
 
-sp<IDataSource> CallbackDataSource::getIDataSource() const {
-    return mIDataSource;
-}
-
 TinyCacheSource::TinyCacheSource(const sp<DataSource>& source)
     : mSource(source), mCachedOffset(0), mCachedSize(0) {
     mName = String8::format("TinyCacheSource(%s)", mSource->toString().string());
@@ -194,8 +190,4 @@
     return mSource->DrmInitialization(mime);
 }
 
-sp<IDataSource> TinyCacheSource::getIDataSource() const {
-    return mSource->getIDataSource();
-}
-
 } // namespace android
diff --git a/media/libstagefright/MediaAdapter.cpp b/media/libstagefright/MediaAdapter.cpp
index d680e0c..74eb1ff 100644
--- a/media/libstagefright/MediaAdapter.cpp
+++ b/media/libstagefright/MediaAdapter.cpp
@@ -45,17 +45,24 @@
 }
 
 status_t MediaAdapter::stop() {
-    Mutex::Autolock autoLock(mAdapterLock);
-    if (mStarted) {
-        mStarted = false;
-        // If stop() happens immediately after a pushBuffer(), we should
-        // clean up the mCurrentMediaBuffer
-        if (mCurrentMediaBuffer != NULL) {
-            mCurrentMediaBuffer->release();
+    MediaBuffer *currentBuffer = NULL;
+    {
+        Mutex::Autolock autoLock(mAdapterLock);
+        if (mStarted) {
+            mStarted = false;
+            // If stop() happens immediately after a pushBuffer(), we should
+            // clean up the mCurrentMediaBuffer. But need to release without
+            // the lock as signalBufferReturned() will acquire the lock.
+            currentBuffer = mCurrentMediaBuffer;
             mCurrentMediaBuffer = NULL;
+
+            // While read() is still waiting, we should signal it to finish.
+            mBufferReadCond.signal();
         }
-        // While read() is still waiting, we should signal it to finish.
-        mBufferReadCond.signal();
+    }
+    if (currentBuffer != NULL) {
+        currentBuffer->release();
+        currentBuffer = NULL;
     }
     return OK;
 }
@@ -97,7 +104,6 @@
 
     *buffer = mCurrentMediaBuffer;
     mCurrentMediaBuffer = NULL;
-    (*buffer)->setObserver(this);
 
     return OK;
 }
@@ -114,6 +120,7 @@
         return INVALID_OPERATION;
     }
     mCurrentMediaBuffer = buffer;
+    mCurrentMediaBuffer->setObserver(this);
     mBufferReadCond.signal();
 
     ALOGV("wait for the buffer returned @ pushBuffer! %p", buffer);
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 1b12510..e1e04eb 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -23,6 +23,7 @@
 #include <media/MediaAnalyticsItem.h>
 #include <media/MediaExtractor.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/FileSource.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MediaExtractorFactory.h>
 #include <media/stagefright/MetaData.h>
@@ -44,7 +45,7 @@
 // static
 sp<IMediaExtractor> MediaExtractorFactory::Create(
         const sp<DataSource> &source, const char *mime) {
-    ALOGV("MediaExtractorFactory::Create %s", mime);
+    ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
 
     if (!property_get_bool("media.stagefright.extractremote", true)) {
         // local extractor
@@ -69,10 +70,48 @@
     return NULL;
 }
 
+// static
+sp<IMediaExtractor> MediaExtractorFactory::CreateFromFd(
+        int fd, int64_t offset, int64_t length, const char *mime, sp<DataSource> *out) {
+    ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
+
+    if (property_get_bool("media.stagefright.extractremote", true)) {
+        // remote extractor
+        ALOGV("get service manager");
+        sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
+
+        if (binder != 0) {
+            sp<IMediaExtractorService> mediaExService(
+                    interface_cast<IMediaExtractorService>(binder));
+            if (!FileSource::requiresDrm(fd, offset, length, nullptr /* mime */)) {
+                ALOGD("FileSource remote");
+                sp<IDataSource> remoteSource =
+                    mediaExService->makeIDataSource(fd, offset, length);
+                ALOGV("IDataSource(FileSource): %p %d %lld %lld",
+                        remoteSource.get(), fd, (long long)offset, (long long)length);
+                if (remoteSource.get() != nullptr) {
+                    // replace the caller's local source with remote source.
+                    *out = CreateDataSourceFromIDataSource(remoteSource);
+                    return mediaExService->makeExtractor(remoteSource, mime);
+                } else {
+                    ALOGW("extractor service cannot make file source."
+                            " falling back to local file source.");
+                }
+            }
+            // Falls back.
+        } else {
+            ALOGE("extractor service not running");
+            return nullptr;
+        }
+    }
+    *out = new FileSource(fd, offset, length);
+    return Create(*out, mime);
+}
+
 sp<MediaExtractor> MediaExtractorFactory::CreateFromService(
         const sp<DataSource> &source, const char *mime) {
 
-    ALOGV("MediaExtractorFactory::CreateFromService %s", mime);
+    ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
     RegisterDefaultSniffers();
 
     // initialize source decryption if needed
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index 983005f..259fb25 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -11,7 +11,6 @@
     cflags: [
         "-Wall",
         "-Werror",
-        "-Wno-unused-variable",
     ],
 
     include_dirs: [
@@ -51,6 +50,11 @@
     ],
     srcs: ["C2SoftAvcDec.cpp"],
 
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
     include_dirs: [
         "external/libavc/decoder",
         "external/libavc/common",
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 9d88895..af73c4e 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -20,6 +20,7 @@
 
 #include <cmath>
 #include <thread>
+#include <cinttypes>
 
 #include "ih264_typedefs.h"
 #include "iv.h"
@@ -1044,7 +1045,8 @@
         work->worklets.front()->output.ordinal = work->input.ordinal;
     };
     if (buffer.capacity() == 0) {
-        ALOGV("empty input: %llu", work->input.ordinal.frame_index);
+        ALOGV("empty input: %" PRIu64, work->input.ordinal.frame_index);
+
         // TODO: result?
         fillEmptyWork(work);
         if ((work->input.flags & C2BufferPack::FLAG_END_OF_STREAM)) {
@@ -1052,7 +1054,7 @@
         }
         done = true;
     } else if (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) {
-        ALOGV("input EOS: %llu", work->input.ordinal.frame_index);
+        ALOGV("input EOS: %" PRIu64, work->input.ordinal.frame_index);
         eos = true;
     }
 
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 1622561..3924fc2 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -304,7 +304,6 @@
 }
 
 status_t SoftAVC::deInitDecoder() {
-    size_t i;
     IV_API_CALL_STATUS_T status;
 
     if (mCodecCtx) {
@@ -451,7 +450,6 @@
             ivd_video_decode_ip_t s_dec_ip;
             ivd_video_decode_op_t s_dec_op;
             IV_API_CALL_STATUS_T status;
-            size_t sizeY, sizeUV;
 
             setDecodeArgs(&s_dec_ip, &s_dec_op, NULL, NULL, 0);
 
@@ -563,7 +561,6 @@
             ivd_video_decode_ip_t s_dec_ip;
             ivd_video_decode_op_t s_dec_op;
             nsecs_t timeDelay, timeTaken;
-            size_t sizeY, sizeUV;
 
             if (!setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx)) {
                 ALOGE("Decoder arg setup failed");
diff --git a/media/libstagefright/include/CallbackDataSource.h b/media/libstagefright/include/CallbackDataSource.h
index 9f413cd..32556d6 100644
--- a/media/libstagefright/include/CallbackDataSource.h
+++ b/media/libstagefright/include/CallbackDataSource.h
@@ -42,7 +42,6 @@
         return mName;
     }
     virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
-    virtual sp<IDataSource> getIDataSource() const;
 
 private:
     sp<IDataSource> mIDataSource;
@@ -71,7 +70,6 @@
         return mName;
     }
     virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
-    virtual sp<IDataSource> getIDataSource() const;
 
 private:
     // 2kb comes from experimenting with the time-to-first-frame from a MediaPlayer
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 96298f9..f216ff8 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -31,6 +31,12 @@
 public:
     static sp<IMediaExtractor> Create(
             const sp<DataSource> &source, const char *mime = NULL);
+    // Creates media extractor from the given file descriptor. To avoid binder calls for
+    // reading file data, this tries to create remote file source in extractor service.
+    // If that fails, this falls back to local file source. The data source used for extractor
+    // will be alsp returned with |out|.
+    static sp<IMediaExtractor> CreateFromFd(
+            int fd, int64_t offset, int64_t length, const char *mime, sp<DataSource> *out);
     static sp<MediaExtractor> CreateFromService(
             const sp<DataSource> &source, const char *mime = NULL);
 
diff --git a/media/libstagefright/include/media/stagefright/RemoteDataSource.h b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
index e191e6a..4ddc5e3 100644
--- a/media/libstagefright/include/media/stagefright/RemoteDataSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
@@ -31,9 +31,6 @@
         if (source.get() == nullptr) {
             return nullptr;
         }
-        if (source->getIDataSource().get() != nullptr) {
-            return source->getIDataSource();
-        }
         return new RemoteDataSource(source);
     }
 
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index 72917dd..f2bc6d0 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -24,7 +24,6 @@
     ],
     shared_libs: [
         "libbinder",
-        "libcutils",
         "liblog",
         "libutils",
         "libmemunreachable",
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index bfb0fe2..979908a 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -67,11 +67,15 @@
     : mPinned(pinned),
       mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
       mDescriptor(*desc),
-      // mConfig is set by configure() and not used before then
+      // clear mConfig to ensure consistent initial value of buffer framecount
+      // in case buffers are associated by setInBuffer() or setOutBuffer()
+      // prior to configure().
+      mConfig{{}, {}},
       mStatus(NO_INIT), mState(IDLE),
-      // mMaxDisableWaitCnt is set by configure() and not used before then
-      // mDisableWaitCnt is set by process() and updateState() and not used before then
+      mMaxDisableWaitCnt(1), // set by configure(), should be >= 1
+      mDisableWaitCnt(0),    // set by process() and updateState()
       mSuspended(false),
+      mOffloaded(false),
       mAudioFlinger(thread->mAudioFlinger)
 #ifdef FLOAT_EFFECT_CHAIN
       , mSupportsFloat(false)
@@ -574,10 +578,14 @@
         }
     }
 
-    mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
-            (1000 * mConfig.outputCfg.buffer.frameCount);
+    // mConfig.outputCfg.buffer.frameCount cannot be zero.
+    mMaxDisableWaitCnt = (uint32_t)std::max(
+            (uint64_t)1, // mMaxDisableWaitCnt must be greater than zero.
+            (uint64_t)MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate
+                / ((uint64_t)1000 * mConfig.outputCfg.buffer.frameCount));
 
 exit:
+    // TODO: consider clearing mConfig on error.
     mStatus = status;
     ALOGVV("configure ended");
     return status;
@@ -892,6 +900,8 @@
 
 void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
     ALOGVV("setInBuffer %p",(&buffer));
+
+    // mConfig.inputCfg.buffer.frameCount may be zero if configure() is not called yet.
     if (buffer != 0) {
         mConfig.inputCfg.buffer.raw = buffer->audioBuffer()->raw;
         buffer->setFrameCount(mConfig.inputCfg.buffer.frameCount);
@@ -934,6 +944,8 @@
 
 void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
     ALOGVV("setOutBuffer %p",(&buffer));
+
+    // mConfig.outputCfg.buffer.frameCount may be zero if configure() is not called yet.
     if (buffer != 0) {
         mConfig.outputCfg.buffer.raw = buffer->audioBuffer()->raw;
         buffer->setFrameCount(mConfig.outputCfg.buffer.frameCount);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 92d98a8..43f6ed6 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -39,14 +39,13 @@
                       DeviceVector &availableOutputDevices,
                       DeviceVector &availableInputDevices,
                       sp<DeviceDescriptor> &defaultOutputDevices,
-                      bool &isSpeakerDrcEnabled,
                       VolumeCurvesCollection *volumes = nullptr)
         : mHwModules(hwModules),
           mAvailableOutputDevices(availableOutputDevices),
           mAvailableInputDevices(availableInputDevices),
           mDefaultOutputDevices(defaultOutputDevices),
           mVolumeCurves(volumes),
-          mIsSpeakerDrcEnabled(isSpeakerDrcEnabled)
+          mIsSpeakerDrcEnabled(false)
     {}
 
     void setVolumes(const VolumeCurvesCollection &volumes)
@@ -80,6 +79,8 @@
         mAvailableOutputDevices.add(availableOutputDevices);
     }
 
+    bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
+
     void setSpeakerDrcEnabled(bool isSpeakerDrcEnabled)
     {
         mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
@@ -140,7 +141,10 @@
     DeviceVector &mAvailableInputDevices;
     sp<DeviceDescriptor> &mDefaultOutputDevices;
     VolumeCurvesCollection *mVolumeCurves;
-    bool &mIsSpeakerDrcEnabled;
+    // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
+    // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
+    // Note: remove also speaker_drc_enabled from global configuration of XML config file.
+    bool mIsSpeakerDrcEnabled;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h
index 7b35f66..e1f6b08 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IVolumeCurvesCollection.h
@@ -25,6 +25,8 @@
 class IVolumeCurvesCollection
 {
 public:
+    virtual ~IVolumeCurvesCollection() = default;
+
     virtual void clearCurrentVolumeIndex(audio_stream_type_t stream) = 0;
     virtual void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device,
                                        int index) = 0;
@@ -46,9 +48,6 @@
                                          audio_devices_t device) const = 0;
 
     virtual status_t dump(int fd) const = 0;
-
-protected:
-    virtual ~IVolumeCurvesCollection() {}
 };
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
index db25ed8..3e6b2b4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
+++ b/services/audiopolicy/common/managerdefinitions/include/VolumeCurve.h
@@ -135,7 +135,13 @@
 
     float volIndexToDb(device_category deviceCat, int indexInUi) const
     {
-        return getCurvesFor(deviceCat)->volIndexToDb(indexInUi, mIndexMin, mIndexMax);
+        sp<VolumeCurve> vc = getCurvesFor(deviceCat);
+        if (vc != 0) {
+            return vc->volIndexToDb(indexInUi, mIndexMin, mIndexMax);
+        } else {
+            ALOGE("Invalid device category %d for Volume Curve", deviceCat);
+            return 0.0f;
+        }
     }
 
     void dump(int fd, int spaces, bool curvePoints = false) const;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index f589743..92332fb 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -223,6 +223,9 @@
                         __FUNCTION__, mDevice, device);
 
     if (status == NO_ERROR) {
+        LOG_ALWAYS_FATAL_IF(*input == AUDIO_IO_HANDLE_NONE,
+                            "%s openInput returned input handle %d for device %08x",
+                            __FUNCTION__, *input, device);
         mSamplingRate = lConfig.sample_rate;
         mChannelMask = lConfig.channel_mask;
         mFormat = lConfig.format;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 6e677e4..044d6db 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -431,6 +431,9 @@
                         __FUNCTION__, mDevice, device);
 
     if (status == NO_ERROR) {
+        LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
+                            "%s openOutput returned output handle %d for device %08x",
+                            __FUNCTION__, *output, device);
         mSamplingRate = lConfig.sample_rate;
         mChannelMask = lConfig.channel_mask;
         mFormat = lConfig.format;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 0e11c5c..ae3dd08 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3474,10 +3474,22 @@
 }
 #endif
 
-AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
+AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface,
+                                       bool /*forTesting*/)
     :
+    mUidCached(getuid()),
+    mpClientInterface(clientInterface),
     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
     mA2dpSuspended(false),
+#ifdef USE_XML_AUDIO_POLICY_CONF
+    mVolumeCurves(new VolumeCurvesCollection()),
+    mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
+            mDefaultOutputDevice, static_cast<VolumeCurvesCollection*>(mVolumeCurves.get())),
+#else
+    mVolumeCurves(new StreamDescriptorCollection()),
+    mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
+            mDefaultOutputDevice),
+#endif
     mAudioPortGeneration(1),
     mBeaconMuteRefCount(0),
     mBeaconPlayingRefCount(0),
@@ -3487,49 +3499,48 @@
     mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
     mHasComputedSoundTriggerSupportsConcurrentCapture(false)
 {
-    mUidCached = getuid();
-    mpClientInterface = clientInterface;
+}
 
-    // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
-    // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
-    // Note: remove also speaker_drc_enabled from global configuration of XML config file.
-    bool speakerDrcEnabled = false;
+AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
+        : AudioPolicyManager(clientInterface, false /*forTesting*/)
+{
+    loadConfig();
+    initialize();
+}
 
+void AudioPolicyManager::loadConfig() {
 #ifdef USE_XML_AUDIO_POLICY_CONF
-    mVolumeCurves = new VolumeCurvesCollection();
-    AudioPolicyConfig config(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
-                             mDefaultOutputDevice, speakerDrcEnabled,
-                             static_cast<VolumeCurvesCollection *>(mVolumeCurves));
-    if (deserializeAudioPolicyXmlConfig(config) != NO_ERROR) {
+    if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
 #else
-    mVolumeCurves = new StreamDescriptorCollection();
-    AudioPolicyConfig config(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
-                             mDefaultOutputDevice, speakerDrcEnabled);
-    if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
-            (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
+    if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, getConfig()) != NO_ERROR)
+           && (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, getConfig()) != NO_ERROR)) {
 #endif
         ALOGE("could not load audio policy configuration file, setting defaults");
-        config.setDefault();
+        getConfig().setDefault();
     }
-    // must be done after reading the policy (since conditionned by Speaker Drc Enabling)
-    mVolumeCurves->initializeVolumeCurves(speakerDrcEnabled);
+}
+
+status_t AudioPolicyManager::initialize() {
+    mVolumeCurves->initializeVolumeCurves(getConfig().isSpeakerDrcEnabled());
 
     // Once policy config has been parsed, retrieve an instance of the engine and initialize it.
     audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
     if (!engineInstance) {
         ALOGE("%s:  Could not get an instance of policy engine", __FUNCTION__);
-        return;
+        return NO_INIT;
     }
     // Retrieve the Policy Manager Interface
     mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>();
     if (mEngine == NULL) {
         ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
-        return;
+        return NO_INIT;
     }
     mEngine->setObserver(this);
     status_t status = mEngine->initCheck();
-    (void) status;
-    ALOG_ASSERT(status == NO_ERROR, "Policy engine not initialized(err=%d)", status);
+    if (status != NO_ERROR) {
+        LOG_FATAL("Policy engine not initialized(err=%d)", status);
+        return status;
+    }
 
     // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
     // open all output streams needed to access attached devices
@@ -3692,11 +3703,16 @@
     // make sure default device is reachable
     if (mDefaultOutputDevice == 0 || mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
         ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type());
+        status = NO_INIT;
     }
 
-    ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output");
+    if (mPrimaryOutput == 0) {
+        ALOGE("Failed to open primary output");
+        status = NO_INIT;
+    }
 
     updateDevicesAndOutputs();
+    return status;
 }
 
 AudioPolicyManager::~AudioPolicyManager()
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 6038e33..611edec 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <atomic>
+#include <memory>
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -33,6 +34,7 @@
 #include <AudioPolicyManagerInterface.h>
 #include <AudioPolicyManagerObserver.h>
 #include <AudioGain.h>
+#include <AudioPolicyConfig.h>
 #include <AudioPort.h>
 #include <AudioPatch.h>
 #include <DeviceDescriptor.h>
@@ -234,6 +236,21 @@
         routing_strategy getStrategy(audio_stream_type_t stream) const;
 
 protected:
+        // A constructor that allows more fine-grained control over initialization process,
+        // used in automatic tests.
+        AudioPolicyManager(AudioPolicyClientInterface *clientInterface, bool forTesting);
+
+        // These methods should be used when finer control over APM initialization
+        // is needed, e.g. in tests. Must be used in conjunction with the constructor
+        // that only performs fields initialization. The public constructor comprises
+        // these steps in the following sequence:
+        //   - field initializing constructor;
+        //   - loadConfig;
+        //   - initialize.
+        AudioPolicyConfig& getConfig() { return mConfig; }
+        void loadConfig();
+        status_t initialize();
+
         // From AudioPolicyManagerObserver
         virtual const AudioPatchCollection &getAudioPatches() const
         {
@@ -526,18 +543,18 @@
         SessionRouteMap mOutputRoutes = SessionRouteMap(SessionRouteMap::MAPTYPE_OUTPUT);
         SessionRouteMap mInputRoutes = SessionRouteMap(SessionRouteMap::MAPTYPE_INPUT);
 
-        IVolumeCurvesCollection *mVolumeCurves; // Volume Curves per use case and device category
-
         bool    mLimitRingtoneVolume;        // limit ringtone volume to music volume if headset connected
         audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
         float   mLastVoiceVolume;            // last voice volume value sent to audio HAL
-
-        EffectDescriptorCollection mEffects;  // list of registered audio effects
         bool    mA2dpSuspended;  // true if A2DP output is suspended
+
+        std::unique_ptr<IVolumeCurvesCollection> mVolumeCurves; // Volume Curves per use case and device category
+        EffectDescriptorCollection mEffects;  // list of registered audio effects
         sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
         HwModuleCollection mHwModules; // contains only modules that have been loaded successfully
         HwModuleCollection mHwModulesAll; // normally not needed, used during construction and for
                                           // dumps
+        AudioPolicyConfig mConfig;
 
         std::atomic<uint32_t> mAudioPortGeneration;
 
diff --git a/services/audiopolicy/tests/Android.mk b/services/audiopolicy/tests/Android.mk
new file mode 100644
index 0000000..a43daea
--- /dev/null
+++ b/services/audiopolicy/tests/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := \
+  frameworks/av/services/audiopolicy \
+  frameworks/av/services/audiopolicy/common/include \
+  frameworks/av/services/audiopolicy/engine/interface \
+  frameworks/av/services/audiopolicy/utilities
+
+LOCAL_SHARED_LIBRARIES := \
+  libaudiopolicymanagerdefault \
+  libbase \
+  liblog \
+  libmedia_helper \
+  libutils \
+
+LOCAL_STATIC_LIBRARIES := \
+  libaudiopolicycomponents \
+
+LOCAL_SRC_FILES := \
+  audiopolicymanager_tests.cpp \
+
+LOCAL_MODULE := audiopolicy_tests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CFLAGS := -Werror -Wall
+
+LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
+
+include $(BUILD_NATIVE_TEST)
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
new file mode 100644
index 0000000..7e0450d
--- /dev/null
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "AudioPolicyInterface.h"
+
+namespace android {
+
+class AudioPolicyTestClient : public AudioPolicyClientInterface
+{
+public:
+    virtual ~AudioPolicyTestClient() = default;
+
+    // AudioPolicyClientInterface Implementation
+    audio_module_handle_t loadHwModule(const char* /*name*/) override { return 0; }
+    status_t openOutput(audio_module_handle_t /*module*/,
+                        audio_io_handle_t* /*output*/,
+                        audio_config_t* /*config*/,
+                        audio_devices_t* /*devices*/,
+                        const String8& /*address*/,
+                        uint32_t* /*latencyMs*/,
+                        audio_output_flags_t /*flags*/) override { return 0; }
+    audio_io_handle_t openDuplicateOutput(audio_io_handle_t /*output1*/,
+                                          audio_io_handle_t /*output2*/) override { return 0; }
+    status_t closeOutput(audio_io_handle_t /*output*/) override { return 0; }
+    status_t suspendOutput(audio_io_handle_t /*output*/) override { return 0; }
+    status_t restoreOutput(audio_io_handle_t /*output*/) override { return 0; }
+    status_t openInput(audio_module_handle_t /*module*/,
+                       audio_io_handle_t* /*input*/,
+                       audio_config_t* /*config*/,
+                       audio_devices_t* /*device*/,
+                       const String8& /*address*/,
+                       audio_source_t /*source*/,
+                       audio_input_flags_t /*flags*/) override { return 0; }
+    status_t closeInput(audio_io_handle_t /*input*/) override { return 0; }
+    status_t setStreamVolume(audio_stream_type_t /*stream*/,
+                             float /*volume*/,
+                             audio_io_handle_t /*output*/,
+                             int /*delayMs*/) override { return 0; }
+    status_t invalidateStream(audio_stream_type_t /*stream*/) override { return 0; }
+    void setParameters(audio_io_handle_t /*ioHandle*/,
+                       const String8& /*keyValuePairs*/,
+                       int /*delayMs*/) override { }
+    String8 getParameters(audio_io_handle_t /*ioHandle*/,
+                          const String8& /*keys*/) override { return String8(); }
+    status_t startTone(audio_policy_tone_t /*tone*/,
+                       audio_stream_type_t /*stream*/) override { return 0; }
+    status_t stopTone() override { return 0; }
+    status_t setVoiceVolume(float /*volume*/, int /*delayMs*/) override { return 0; }
+    status_t moveEffects(audio_session_t /*session*/,
+                         audio_io_handle_t /*srcOutput*/,
+                         audio_io_handle_t /*dstOutput*/) override { return 0; }
+    status_t createAudioPatch(const struct audio_patch* /*patch*/,
+                              audio_patch_handle_t* /*handle*/,
+                              int /*delayMs*/) override { return 0; }
+    status_t releaseAudioPatch(audio_patch_handle_t /*handle*/,
+                               int /*delayMs*/) override { return 0; }
+    status_t setAudioPortConfig(const struct audio_port_config* /*config*/,
+                                int /*delayMs*/) override { return 0; }
+    void onAudioPortListUpdate() override { }
+    void onAudioPatchListUpdate() override { }
+    audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t /*use*/) override { return 0; }
+    void onDynamicPolicyMixStateUpdate(String8 /*regId*/, int32_t /*state*/) override { }
+    void onRecordingConfigurationUpdate(int /*event*/,
+                                        const record_client_info_t* /*clientInfo*/,
+                                        const struct audio_config_base* /*clientConfig*/,
+                                        const struct audio_config_base* /*deviceConfig*/,
+                                        audio_patch_handle_t /*patchHandle*/) override { }
+};
+
+} // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
new file mode 100644
index 0000000..fe543a6
--- /dev/null
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "managerdefault/AudioPolicyManager.h"
+
+namespace android {
+
+class AudioPolicyTestManager : public AudioPolicyManager {
+  public:
+    explicit AudioPolicyTestManager(AudioPolicyClientInterface *clientInterface)
+            : AudioPolicyManager(clientInterface, true /*forTesting*/) { }
+    using AudioPolicyManager::getConfig;
+    using AudioPolicyManager::initialize;
+};
+
+}  // namespace android
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
new file mode 100644
index 0000000..de26ab0
--- /dev/null
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "AudioPolicyTestClient.h"
+#include "AudioPolicyTestManager.h"
+
+using namespace android;
+
+TEST(AudioPolicyManager, InitFailure) {
+    AudioPolicyTestClient client;
+    AudioPolicyTestManager manager(&client);
+    manager.getConfig().setDefault();
+    // Since the default client fails to open anything,
+    // APM should indicate that the initialization didn't succeed.
+    ASSERT_EQ(NO_INIT, manager.initialize());
+    ASSERT_EQ(NO_INIT, manager.initCheck());
+}
+
+
+// A client that provides correct module and IO handles for inputs and outputs.
+class AudioPolicyTestClientWithModulesIoHandles : public AudioPolicyTestClient {
+  public:
+    audio_module_handle_t loadHwModule(const char* /*name*/) override {
+        return mNextModule++;
+    }
+    status_t openOutput(audio_module_handle_t module,
+                        audio_io_handle_t* output,
+                        audio_config_t* /*config*/,
+                        audio_devices_t* /*devices*/,
+                        const String8& /*address*/,
+                        uint32_t* /*latencyMs*/,
+                        audio_output_flags_t /*flags*/) override {
+        if (module >= mNextModule) {
+            ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
+                    __func__, module, mNextModule);
+            return BAD_VALUE;
+        }
+        *output = mNextIoHandle++;
+        return NO_ERROR;
+    }
+    status_t openInput(audio_module_handle_t module,
+                       audio_io_handle_t* input,
+                       audio_config_t* /*config*/,
+                       audio_devices_t* /*device*/,
+                       const String8& /*address*/,
+                       audio_source_t /*source*/,
+                       audio_input_flags_t /*flags*/) override {
+        if (module >= mNextModule) {
+            ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
+                    __func__, module, mNextModule);
+            return BAD_VALUE;
+        }
+        *input = mNextIoHandle++;
+        return NO_ERROR;
+    }
+  private:
+    audio_module_handle_t mNextModule = AUDIO_MODULE_HANDLE_NONE + 1;
+    audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
+};
+
+TEST(AudioPolicyManager, InitSuccess) {
+    AudioPolicyTestClientWithModulesIoHandles client;
+    AudioPolicyTestManager manager(&client);
+    manager.getConfig().setDefault();
+    ASSERT_EQ(NO_ERROR, manager.initialize());
+    ASSERT_EQ(NO_ERROR, manager.initCheck());
+}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index a376ab4..24b0816 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -672,7 +672,7 @@
 
     if (mInputStream.configured) {
         String8 msg = String8::format("Camera %s: Already has an input stream "
-                "configured (ID %zd)", mCameraIdStr.string(), mInputStream.id);
+                "configured (ID %d)", mCameraIdStr.string(), mInputStream.id);
         ALOGE("%s: %s", __FUNCTION__, msg.string() );
         return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.string());
     }
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index 120a717..ca31691 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -25,10 +25,6 @@
 LOCAL_32_BIT_ONLY := true
 LOCAL_INIT_RC := android.hardware.media.omx@1.0-service.rc
 
-ifeq ($(PRODUCT_FULL_TREBLE),true)
-LOCAL_CFLAGS += -DUSE_VNDBINDER
-endif
-
 include $(BUILD_EXECUTABLE)
 
 # service seccomp policy
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index 6f14a42..701ca6e 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -40,10 +40,8 @@
     signal(SIGPIPE, SIG_IGN);
     SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
 
-#ifdef USE_VNDBINDER
     android::ProcessState::initWithDriver("/dev/vndbinder");
     android::ProcessState::self()->startThreadPool();
-#endif // USE_VNDBINDER
 
     ::android::hardware::configureRpcThreadpool(64, false);