Merge "stagefright: Move CodecCapabilities querying into MediaCodec" into nyc-dev
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 7d75108..e5fbba0 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -9,7 +9,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright libmedia libutils libbinder libstagefright_foundation \
-        libjpeg libgui libcutils liblog libui
+	libjpeg libgui libcutils liblog
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -31,8 +31,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
-        SineSource.cpp    \
-        record.cpp
+	SineSource.cpp    \
+	record.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright libmedia liblog libutils libbinder libstagefright_foundation
@@ -55,8 +55,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
-        SineSource.cpp    \
-        recordvideo.cpp
+	SineSource.cpp    \
+	recordvideo.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright libmedia liblog libutils libbinder libstagefright_foundation
@@ -80,8 +80,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
-        SineSource.cpp    \
-        audioloop.cpp
+	SineSource.cpp    \
+	audioloop.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright libmedia liblog libutils libbinder libstagefright_foundation
@@ -108,7 +108,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright liblog libutils libbinder libgui \
-        libstagefright_foundation libmedia libcutils
+	libstagefright_foundation libmedia libcutils
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -128,11 +128,11 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
-        sf2.cpp    \
+	sf2.cpp    \
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright liblog libutils libbinder libstagefright_foundation \
-        libmedia libgui libcutils libui
+	libmedia libgui libcutils libui
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -152,12 +152,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=               \
-        codec.cpp               \
-        SimplePlayer.cpp        \
+	codec.cpp               \
+	SimplePlayer.cpp        \
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright liblog libutils libbinder libstagefright_foundation \
-        libmedia libgui libcutils libui
+	libmedia libgui libcutils libui
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
@@ -220,11 +220,11 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=               \
-        muxer.cpp            \
+	muxer.cpp            \
 
 LOCAL_SHARED_LIBRARIES := \
 	libstagefright liblog libutils libbinder libstagefright_foundation \
-        libmedia libgui libcutils libui libc
+	libmedia libgui libcutils libui libc
 
 LOCAL_C_INCLUDES:= \
 	frameworks/av/media/libstagefright \
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index db0c12d..ed44b4d 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -23,13 +23,14 @@
 #include <binder/ProcessState.h>
 #include <media/mediarecorder.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/AMRWriter.h>
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/AudioSource.h>
+#include <media/stagefright/MediaCodecSource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/SimpleDecodingSource.h>
 #include "SineSource.h"
 
 using namespace android;
@@ -79,8 +80,6 @@
     const int32_t kBitRate = outputWBAMR ? 16000 : 8000;
 
     android::ProcessState::self()->startThreadPool();
-    OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
     sp<MediaSource> source;
 
     if (useMic) {
@@ -95,24 +94,25 @@
         source = new SineSource(kSampleRate, channels);
     }
 
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(
-            kKeyMIMEType,
+    sp<AMessage> meta = new AMessage;
+    meta->setString(
+            "mime",
             outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
                     : MEDIA_MIMETYPE_AUDIO_AMR_NB);
 
-    meta->setInt32(kKeyChannelCount, channels);
-    meta->setInt32(kKeySampleRate, kSampleRate);
-    meta->setInt32(kKeyBitRate, kBitRate);
+    meta->setInt32("channel-count", channels);
+    meta->setInt32("sample-rate", kSampleRate);
+    meta->setInt32("bitrate", kBitRate);
     int32_t maxInputSize;
     if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) {
-        meta->setInt32(kKeyMaxInputSize, maxInputSize);
+        meta->setInt32("max-input-size", maxInputSize);
     }
 
-    sp<IMediaSource> encoder = OMXCodec::Create(
-            client.interface(),
-            meta, true /* createEncoder */,
-            source);
+    sp<ALooper> looper = new ALooper;
+    looper->setName("audioloop");
+    looper->start();
+
+    sp<IMediaSource> encoder = MediaCodecSource::Create(looper, meta, source);
 
     if (fileOut != NULL) {
         // target file specified, write encoded AMR output
@@ -128,17 +128,15 @@
         writer->stop();
     } else {
         // otherwise decode to speaker
-        sp<IMediaSource> decoder = OMXCodec::Create(
-                client.interface(),
-                meta, false /* createEncoder */,
-                encoder);
+        sp<IMediaSource> decoder = SimpleDecodingSource::Create(encoder);
 
         if (playToSpeaker) {
             AudioPlayer *player = new AudioPlayer(NULL);
             player->setSource(decoder);
             player->start();
             sleep(duration);
-            source->stop(); // must stop source otherwise delete player will hang
+
+            decoder.clear(); // must clear |decoder| otherwise delete player will hang.
             delete player; // there is no player->stop()...
         } else {
             CHECK_EQ(decoder->start(), (status_t)OK);
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index cd9c8dc..f8b2f68 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -18,16 +18,18 @@
 
 #include <binder/ProcessState.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/CameraSource.h>
 #include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaCodecSource.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MPEG4Writer.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/SimpleDecodingSource.h>
 #include <media/MediaPlayerInterface.h>
 
 using namespace android;
@@ -182,9 +184,6 @@
         fprintf(stderr, "input color format must be 0 (YUV420SP) or 1 (YUV420P)\n");
         return 1;
     }
-    OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
-
     status_t err = OK;
 
 #if 0
@@ -197,8 +196,7 @@
 
     sp<MetaData> meta = source->getFormat();
 
-    sp<MediaSource> decoder = OMXCodec::Create(
-            client.interface(), meta, false /* createEncoder */, source);
+    sp<MediaSource> decoder = SimpleDecodingSource::Create(source);
 
     int width, height;
     bool success = meta->findInt32(kKeyWidth, &width);
@@ -210,22 +208,21 @@
     sp<MediaSource> decoder = new DummySource(width, height, colorFormat);
 #endif
 
-    sp<MetaData> enc_meta = new MetaData;
-    // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
-    // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
-    enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
-    enc_meta->setInt32(kKeyWidth, width);
-    enc_meta->setInt32(kKeyHeight, height);
-    enc_meta->setInt32(kKeySampleRate, kFramerate);
-    enc_meta->setInt32(kKeyBitRate, kVideoBitRate);
-    enc_meta->setInt32(kKeyStride, width);
-    enc_meta->setInt32(kKeySliceHeight, height);
-    enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
-    enc_meta->setInt32(kKeyColorFormat, colorFormat);
+    sp<AMessage> enc_meta = new AMessage;
+    // enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
+    // enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
+    enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
+    enc_meta->setInt32("width", width);
+    enc_meta->setInt32("height", height);
+    enc_meta->setInt32("sample-rate", kFramerate);
+    enc_meta->setInt32("bit-rate", kVideoBitRate);
+    // enc_meta->setInt32("stride", width);
+    // enc_meta->setInt32("slice-height", height);
+    enc_meta->setInt32("i-frame-interval", kIFramesIntervalSec);
+    enc_meta->setInt32("color-format", colorFormat);
 
     sp<MediaSource> encoder =
-        OMXCodec::Create(
-                client.interface(), enc_meta, true /* createEncoder */, decoder);
+        MediaCodecSource::Create(looper, format, decoder);
 
 #if 1
     sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
@@ -260,7 +257,6 @@
 #endif
 
     printf("$\n");
-    client.disconnect();
 #endif
 
 #if 0
@@ -299,9 +295,6 @@
 int main(int /* argc */, char ** /* argv */) {
     android::ProcessState::self()->startThreadPool();
 
-    OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
-
     const int32_t kSampleRate = 22050;
     const int32_t kNumChannels = 2;
     sp<MediaSource> audioSource = new SineSource(kSampleRate, kNumChannels);
@@ -317,16 +310,20 @@
     player->stop();
 #endif
 
-    sp<MetaData> encMeta = new MetaData;
-    encMeta->setCString(kKeyMIMEType,
+    sp<AMessage> encMeta = new AMessage;
+    encMeta->setString("mime",
             0 ? MEDIA_MIMETYPE_AUDIO_AMR_WB : MEDIA_MIMETYPE_AUDIO_AAC);
-    encMeta->setInt32(kKeySampleRate, kSampleRate);
-    encMeta->setInt32(kKeyChannelCount, kNumChannels);
-    encMeta->setInt32(kKeyMaxInputSize, 8192);
-    encMeta->setInt32(kKeyBitRate, kAudioBitRate);
+    encMeta->setInt32("sample-rate", kSampleRate);
+    encMeta->setInt32("channel-count", kNumChannels);
+    encMeta->setInt32("max-input-size", 8192);
+    encMeta->setInt32("bitrate", kAudioBitRate);
+
+    sp<ALooper> looper = new ALooper;
+    looper->setName("record");
+    looper->start();
 
     sp<IMediaSource> encoder =
-        OMXCodec::Create(client.interface(), encMeta, true, audioSource);
+        MediaCodecSource::Create(looper, encMeta, audioSource);
 
     encoder->start();
 
@@ -348,8 +345,6 @@
 
     encoder->stop();
 
-    client.disconnect();
-
     return 0;
 }
 #endif
diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp
index 05b50be..7a3c842 100644
--- a/cmds/stagefright/recordvideo.cpp
+++ b/cmds/stagefright/recordvideo.cpp
@@ -23,15 +23,18 @@
 
 #include <binder/ProcessState.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaCodecSource.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MPEG4Writer.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
 #include <media/MediaPlayerInterface.h>
 
+#include <OMX_Video.h>
+
 using namespace android;
 
 // Print usage showing how to use this utility to record videos
@@ -265,44 +268,45 @@
         }
     }
 
-    OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
-
     status_t err = OK;
     sp<MediaSource> source =
         new DummySource(width, height, nFrames, frameRateFps, colorFormat);
 
-    sp<MetaData> enc_meta = new MetaData;
+    sp<AMessage> enc_meta = new AMessage;
     switch (codec) {
         case 1:
-            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+            enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
             break;
         case 2:
-            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+            enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
             break;
         default:
-            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+            enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
             break;
     }
-    enc_meta->setInt32(kKeyWidth, width);
-    enc_meta->setInt32(kKeyHeight, height);
-    enc_meta->setInt32(kKeyFrameRate, frameRateFps);
-    enc_meta->setInt32(kKeyBitRate, bitRateBps);
-    enc_meta->setInt32(kKeyStride, width);
-    enc_meta->setInt32(kKeySliceHeight, height);
-    enc_meta->setInt32(kKeyIFramesInterval, iFramesIntervalSeconds);
-    enc_meta->setInt32(kKeyColorFormat, colorFormat);
+    enc_meta->setInt32("width", width);
+    enc_meta->setInt32("height", height);
+    enc_meta->setInt32("frame-rate", frameRateFps);
+    enc_meta->setInt32("bitrate", bitRateBps);
+    enc_meta->setInt32("stride", width);
+    enc_meta->setInt32("slice-height", height);
+    enc_meta->setInt32("i-frame-interval", iFramesIntervalSeconds);
+    enc_meta->setInt32("color-format", colorFormat);
     if (level != -1) {
-        enc_meta->setInt32(kKeyVideoLevel, level);
+        enc_meta->setInt32("level", level);
     }
     if (profile != -1) {
-        enc_meta->setInt32(kKeyVideoProfile, profile);
+        enc_meta->setInt32("profile", profile);
     }
 
+    sp<ALooper> looper = new ALooper;
+    looper->setName("recordvideo");
+    looper->start();
+
     sp<IMediaSource> encoder =
-        OMXCodec::Create(
-                client.interface(), enc_meta, true /* createEncoder */, source,
-                0, preferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0);
+        MediaCodecSource::Create(
+                looper, enc_meta, source, NULL /* consumer */,
+                preferSoftwareCodec ? MediaCodecSource::FLAG_PREFER_SOFTWARE_CODEC : 0);
 
     int fd = open(fileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
     if (fd < 0) {
@@ -321,7 +325,6 @@
     int64_t end = systemTime();
 
     fprintf(stderr, "$\n");
-    client.disconnect();
 
     if (err != OK && err != ERROR_END_OF_STREAM) {
         fprintf(stderr, "record failed: %d\n", err);
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 9537daa..ca68722 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -31,20 +31,27 @@
 
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
+#include <media/ICrypto.h>
 #include <media/IMediaHTTPService.h>
+#include <media/IMediaCodecService.h>
 #include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include "include/NuCachedSource2.h"
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/JPEGSource.h>
+#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/SimpleDecodingSource.h>
+#include <media/stagefright/Utils.h>
 #include <media/mediametadataretriever.h>
 
 #include <media/stagefright/foundation/hexdump.h>
@@ -164,7 +171,7 @@
     out = NULL;
 }
 
-static void playSource(OMXClient *client, sp<IMediaSource> &source) {
+static void playSource(sp<IMediaSource> &source) {
     sp<MetaData> meta = source->getFormat();
 
     const char *mime;
@@ -176,20 +183,14 @@
     } else {
         int flags = 0;
         if (gPreferSoftwareCodec) {
-            flags |= OMXCodec::kPreferSoftwareCodecs;
+            flags |= MediaCodecList::kPreferSoftwareCodecs;
         }
         if (gForceToUseHardwareCodec) {
             CHECK(!gPreferSoftwareCodec);
-            flags |= OMXCodec::kHardwareCodecsOnly;
+            flags |= MediaCodecList::kHardwareCodecsOnly;
         }
-        rawSource = OMXCodec::Create(
-            client->interface(), meta, false /* createEncoder */, source,
-            NULL /* matchComponentName */,
-            flags,
-            gSurface);
-
+        rawSource = SimpleDecodingSource::Create(source, flags, gSurface);
         if (rawSource == NULL) {
-            fprintf(stderr, "Failed to instantiate decoder for '%s'.\n", mime);
             return;
         }
         displayAVCProfileLevelIfPossible(meta);
@@ -343,12 +344,6 @@
                     printf(".");
                     fflush(stdout);
                 }
-
-                // render buffers from OMXCodec
-                if (buffer->graphicBuffer() != NULL && gSurface != NULL) {
-                    gSurface->queueBuffer(gSurface.get(), buffer->graphicBuffer()->getNativeBuffer(), -1);
-                    buffer->meta_data()->setInt32(kKeyRendered, 1);
-                }
             }
 
             sumDecodeUs += delayDecodeUs;
@@ -628,7 +623,7 @@
     fprintf(stderr, "       -D(ump) output_filename (decoded PCM data to a file)\n");
 }
 
-static void dumpCodecProfiles(const sp<IOMX>& omx, bool queryDecoders) {
+static void dumpCodecProfiles(bool queryDecoders) {
     const char *kMimeTypes[] = {
         MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
         MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AAC,
@@ -642,30 +637,36 @@
     const char *codecType = queryDecoders? "decoder" : "encoder";
     printf("%s profiles:\n", codecType);
 
+    sp<IMediaCodecList> list = MediaCodecList::getInstance();
+    size_t numCodecs = list->countCodecs();
+
     for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]); ++k) {
         printf("type '%s':\n", kMimeTypes[k]);
 
-        Vector<CodecCapabilities> results;
-        // will retrieve hardware and software codecs
-        CHECK_EQ(QueryCodecs(omx, kMimeTypes[k],
-                             queryDecoders,
-                             &results), (status_t)OK);
-
-        for (size_t i = 0; i < results.size(); ++i) {
+        for (size_t index = 0; index < numCodecs; ++index) {
+            sp<MediaCodecInfo> info = list->getCodecInfo(index);
+            if (info == NULL || info->isEncoder() != !queryDecoders) {
+                continue;
+            }
+            sp<MediaCodecInfo::Capabilities> caps = info->getCapabilitiesFor(kMimeTypes[k]);
+            if (caps == NULL) {
+                continue;
+            }
             printf("  %s '%s' supports ",
-                       codecType, results[i].mComponentName.string());
+                       codecType, info->getCodecName());
 
-            if (results[i].mProfileLevels.size() == 0) {
-                    printf("NOTHING.\n");
-                    continue;
+            Vector<MediaCodecInfo::ProfileLevel> profileLevels;
+            caps->getSupportedProfileLevels(&profileLevels);
+            if (profileLevels.size() == 0) {
+                printf("NOTHING.\n");
+                continue;
             }
 
-            for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
-                const CodecProfileLevel &profileLevel =
-                     results[i].mProfileLevels[j];
+            for (size_t j = 0; j < profileLevels.size(); ++j) {
+                const MediaCodecInfo::ProfileLevel &profileLevel = profileLevels[j];
 
-                printf("%s%" PRIu32 "/%" PRIu32, j > 0 ? ", " : "",
-                    profileLevel.mProfile, profileLevel.mLevel);
+                printf("%s%u/%u", j > 0 ? ", " : "",
+                        profileLevel.mProfile, profileLevel.mLevel);
             }
 
             printf("\n");
@@ -898,23 +899,14 @@
     }
 
     if (dumpProfiles) {
-        sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder = sm->getService(String16("media.player"));
-        sp<IMediaPlayerService> service =
-            interface_cast<IMediaPlayerService>(binder);
-
-        CHECK(service.get() != NULL);
-
-        sp<IOMX> omx = service->getOMX();
-        CHECK(omx.get() != NULL);
-        dumpCodecProfiles(omx, true /* queryDecoders */);
-        dumpCodecProfiles(omx, false /* queryDecoders */);
+        dumpCodecProfiles(true /* queryDecoders */);
+        dumpCodecProfiles(false /* queryDecoders */);
     }
 
     if (listComponents) {
         sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder = sm->getService(String16("media.player"));
-        sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+        sp<IBinder> binder = sm->getService(String16("media.codec"));
+        sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
 
         CHECK(service.get() != NULL);
 
@@ -971,16 +963,11 @@
                     false /* isControlledByApp */);
             gSurface = new Surface(producer);
         }
-
-        CHECK_EQ((status_t)OK,
-                 native_window_api_connect(
-                     gSurface.get(), NATIVE_WINDOW_API_MEDIA));
     }
 
     DataSource::RegisterDefaultSniffers();
 
-    OMXClient client;
-    status_t err = client.connect();
+    status_t err = OK;
 
     for (int k = 0; k < argc && err == OK; ++k) {
         bool syncInfoPresent = true;
@@ -1120,31 +1107,16 @@
         } else if (dumpStream) {
             dumpSource(mediaSource, dumpStreamFilename);
         } else if (dumpPCMStream) {
-            OMXClient client;
-            CHECK_EQ(client.connect(), (status_t)OK);
-
-            sp<IMediaSource> decSource =
-                OMXCodec::Create(
-                        client.interface(),
-                        mediaSource->getFormat(),
-                        false,
-                        mediaSource,
-                        0,
-                        0);
-
+            sp<IMediaSource> decSource = SimpleDecodingSource::Create(mediaSource);
             dumpSource(decSource, dumpStreamFilename);
         } else if (seekTest) {
             performSeekTest(mediaSource);
         } else {
-            playSource(&client, mediaSource);
+            playSource(mediaSource);
         }
     }
 
     if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
-        CHECK_EQ((status_t)OK,
-                 native_window_api_disconnect(
-                     gSurface.get(), NATIVE_WINDOW_API_MEDIA));
-
         gSurface.clear();
 
         if (useSurfaceAlloc) {
@@ -1152,7 +1124,5 @@
         }
     }
 
-    client.disconnect();
-
     return 0;
 }
diff --git a/include/media/IMediaCodecService.h b/include/media/IMediaCodecService.h
new file mode 100644
index 0000000..984a0fd
--- /dev/null
+++ b/include/media/IMediaCodecService.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_IMEDIACODECSERVICE_H
+#define ANDROID_IMEDIACODECSERVICE_H
+
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <media/IDataSource.h>
+#include <include/OMX.h>
+
+namespace android {
+
+class IMediaCodecService: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(MediaCodecService);
+
+    virtual sp<IOMX> getOMX() = 0;
+};
+
+class BnMediaCodecService: public BnInterface<IMediaCodecService>
+{
+public:
+    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                uint32_t flags = 0);
+};
+
+}   // namespace android
+
+#endif  // ANDROID_IMEDIACODECSERVICE_H
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index a316ce2..99ca6f0 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -51,7 +51,6 @@
     virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0;
     virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId = 0)
             = 0;
-
     virtual sp<IOMX>            getOMX() = 0;
     virtual sp<ICrypto>         makeCrypto() = 0;
     virtual sp<IDrm>            makeDrm() = 0;
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index b495f91..f7499b6 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -21,7 +21,6 @@
 #include <media/IMediaSource.h>
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/TimeSource.h>
 #include <utils/threads.h>
 
 namespace android {
@@ -30,7 +29,7 @@
 class AudioTrack;
 struct AwesomePlayer;
 
-class AudioPlayer : public TimeSource {
+class AudioPlayer {
 public:
     enum {
         REACHED_EOS,
@@ -46,29 +45,18 @@
     };
 
     AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink,
-                uint32_t flags = 0,
-                AwesomePlayer *audioObserver = NULL);
+                uint32_t flags = 0);
 
     virtual ~AudioPlayer();
 
     // Caller retains ownership of "source".
     void setSource(const sp<IMediaSource> &source);
 
-    // Return time in us.
-    virtual int64_t getRealTimeUs();
-
     status_t start(bool sourceAlreadyStarted = false);
 
     void pause(bool playPendingSamples = false);
     status_t resume();
 
-    // Returns the timestamp of the last buffer played (in us).
-    int64_t getMediaTimeUs();
-
-    // Returns true iff a mapping is established, i.e. the AudioPlayer
-    // has played at least one frame of audio.
-    bool getMediaTimeMapping(int64_t *realtime_us, int64_t *mediatime_us);
-
     status_t seekTo(int64_t time_us);
 
     bool isSeeking();
@@ -77,10 +65,7 @@
     status_t setPlaybackRate(const AudioPlaybackRate &rate);
     status_t getPlaybackRate(AudioPlaybackRate *rate /* nonnull */);
 
-    void notifyAudioEOS();
-
 private:
-    friend class VideoEditorAudioPlayer;
     sp<IMediaSource> mSource;
     sp<AudioTrack> mAudioTrack;
 
@@ -109,8 +94,6 @@
     MediaBuffer *mFirstBuffer;
 
     sp<MediaPlayerBase::AudioSink> mAudioSink;
-    AwesomePlayer *mObserver;
-    int64_t mPinnedTimeUs;
 
     bool mPlaying;
     int64_t mStartPosUs;
@@ -126,11 +109,8 @@
 
     size_t fillBuffer(void *data, size_t size);
 
-    int64_t getRealTimeUsLocked() const;
-
     void reset();
 
-    uint32_t getNumFramesPendingPlayout() const;
     int64_t getOutputPlayPositionUs_l();
 
     bool allowDeepBuffering() const { return (mCreateFlags & ALLOW_DEEP_BUFFERING) != 0; }
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index d147b57..e3f3f5e 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -19,6 +19,7 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AHandlerReflector.h>
+#include <media/stagefright/foundation/Mutexed.h>
 #include <media/stagefright/MediaSource.h>
 
 #include <gui/IGraphicBufferConsumer.h>
@@ -79,6 +80,7 @@
         kWhatStop,
         kWhatPause,
         kWhatSetInputBufferTimeOffset,
+        kWhatStopStalled,
     };
 
     MediaCodecSource(
@@ -127,12 +129,16 @@
     int64_t mFirstSampleTimeUs;
     List<int64_t> mDriftTimeQueue;
 
-    // following variables are protected by mOutputBufferLock
-    Mutex mOutputBufferLock;
-    Condition mOutputBufferCond;
-    List<MediaBuffer*> mOutputBufferQueue;
-    bool mEncoderReachedEOS;
-    status_t mErrorCode;
+    struct Output {
+        Output();
+        List<MediaBuffer*> mBufferQueue;
+        bool mEncoderReachedEOS;
+        status_t mErrorCode;
+        Condition mCond;
+    };
+    Mutexed<Output> mOutput;
+
+    int32_t mGeneration;
 
     DISALLOW_EVIL_CONSTRUCTORS(MediaCodecSource);
 };
diff --git a/include/media/stagefright/SimpleDecodingSource.h b/include/media/stagefright/SimpleDecodingSource.h
new file mode 100644
index 0000000..6bd82c4
--- /dev/null
+++ b/include/media/stagefright/SimpleDecodingSource.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2016, 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.
+ */
+
+#ifndef SIMPLE_DECODING_SOURCE_H_
+#define SIMPLE_DECODING_SOURCE_H_
+
+#include <system/window.h>
+
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/Mutexed.h>
+
+#include <utils/Condition.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+struct ALooper;
+struct AMessage;
+class MediaBuffer;
+struct MediaCodec;
+class MetaData;
+
+class SimpleDecodingSource : public MediaSource {
+public:
+    // Creates a MediaSource that uses MediaCodec to decode a compressed input |source|.
+    // The selected codec can be influenced using |flags|. This source only supports the
+    // kPreferGoogleCodec and kNonGoogleCodecsOnly |flags| - MediaCodecList.
+    // You can pass in a target |nativeWindow| to render video directly onto a surface. In this
+    // case the source will return empty buffers.
+    // This source cannot be restarted (hence the name "Simple"), all reads are blocking, and
+    // does not support secure input or pausing.
+    static sp<SimpleDecodingSource> Create(
+            const sp<IMediaSource> &source, uint32_t flags = 0,
+            const sp<ANativeWindow> &nativeWindow = NULL);
+
+    virtual ~SimpleDecodingSource();
+
+    // starts this source (and it's underlying source). |params| is ignored.
+    virtual status_t start(MetaData *params = NULL);
+
+    // stops this source (and it's underlying source).
+    virtual status_t stop();
+
+    // returns the output format of this source.
+    virtual sp<MetaData> getFormat();
+
+    // reads from the source. This call always blocks.
+    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options);
+
+    // unsupported methods
+    virtual status_t pause() { return INVALID_OPERATION; }
+    virtual status_t setBuffers(const Vector<MediaBuffer *> &) { return INVALID_OPERATION; }
+
+private:
+    // Construct this using a codec, source and looper.
+    SimpleDecodingSource(
+            const sp<MediaCodec> &codec, const sp<IMediaSource> &source, const sp<ALooper> &looper,
+            bool usingSurface, const sp<AMessage> &format);
+
+    sp<MediaCodec> mCodec;
+    sp<IMediaSource> mSource;
+    sp<ALooper> mLooper;
+    bool mUsingSurface;
+    enum State {
+        INIT,
+        STARTED,
+        STOPPING,
+        STOPPED,
+        ERROR,
+    };
+    AString mComponentName;
+
+    struct ProtectedState {
+        ProtectedState(const sp<AMessage> &format);
+        bool mReading;
+        Condition mReadCondition;
+
+        sp<AMessage> mFormat;
+        State mState;
+        bool mQueuedInputEOS;
+        bool mGotOutputEOS;
+    };
+    Mutexed<ProtectedState> mProtectedState;
+
+    // do the actual reading
+    status_t doRead(
+            Mutexed<ProtectedState>::Locked &me, MediaBuffer **buffer, const ReadOptions *options);
+};
+
+} // namespace android
+
+#endif
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 285c33e..c095724 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -30,6 +30,7 @@
     AudioSystem.cpp \
     mediaplayer.cpp \
     IMediaCodecList.cpp \
+    IMediaCodecService.cpp \
     IMediaHTTPConnection.cpp \
     IMediaHTTPService.cpp \
     IMediaLogService.cpp \
diff --git a/media/libmedia/IMediaCodecService.cpp b/media/libmedia/IMediaCodecService.cpp
new file mode 100644
index 0000000..dcf2b27
--- /dev/null
+++ b/media/libmedia/IMediaCodecService.cpp
@@ -0,0 +1,72 @@
+/*
+**
+** Copyright 2015, 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.
+*/
+
+#define LOG_TAG "IMediaCodecService"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <media/IMediaCodecService.h>
+
+namespace android {
+
+enum {
+    GET_OMX = IBinder::FIRST_CALL_TRANSACTION
+};
+
+class BpMediaCodecService : public BpInterface<IMediaCodecService>
+{
+public:
+    BpMediaCodecService(const sp<IBinder>& impl)
+        : BpInterface<IMediaCodecService>(impl)
+    {
+    }
+
+    virtual sp<IOMX> getOMX() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaCodecService::getInterfaceDescriptor());
+        remote()->transact(GET_OMX, data, &reply);
+        return interface_cast<IOMX>(reply.readStrongBinder());
+    }
+
+};
+
+IMPLEMENT_META_INTERFACE(MediaCodecService, "android.media.IMediaCodecService");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaCodecService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+
+        case GET_OMX: {
+            CHECK_INTERFACE(IMediaCodecService, data, reply);
+            sp<IOMX> omx = getOMX();
+            reply->writeStrongBinder(IInterface::asBinder(omx));
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+} // namespace android
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 4d1b587..81f2af3 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -18,7 +18,6 @@
     MetadataRetrieverClient.cpp \
     RemoteDisplay.cpp           \
     SharedLibrary.cpp           \
-    StagefrightPlayer.cpp       \
     StagefrightRecorder.cpp     \
     TestPlayerStub.cpp          \
 
@@ -45,6 +44,7 @@
 LOCAL_STATIC_LIBRARIES :=       \
     libstagefright_nuplayer     \
     libstagefright_rtsp         \
+    libstagefright_timedtext    \
 
 LOCAL_C_INCLUDES :=                                                 \
     $(TOP)/frameworks/av/media/libstagefright/include               \
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index d5d12f7..605c710 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -31,7 +31,6 @@
 #include "MediaPlayerFactory.h"
 
 #include "TestPlayerStub.h"
-#include "StagefrightPlayer.h"
 #include "nuplayer/NuPlayerDriver.h"
 
 namespace android {
@@ -64,12 +63,6 @@
 }
 
 static player_type getDefaultPlayerType() {
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("media.stagefright.use-awesome", value, NULL)
-            && (!strcmp("1", value) || !strcasecmp("true", value))) {
-        return STAGEFRIGHT_PLAYER;
-    }
-
     return NU_PLAYER;
 }
 
@@ -176,63 +169,6 @@
  *                                                                           *
  *****************************************************************************/
 
-class StagefrightPlayerFactory :
-    public MediaPlayerFactory::IFactory {
-  public:
-    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
-                               int fd,
-                               int64_t offset,
-                               int64_t length,
-                               float /*curScore*/) {
-        if (legacyDrm()) {
-            sp<DataSource> source = new FileSource(dup(fd), offset, length);
-            String8 mimeType;
-            float confidence;
-            if (SniffWVM(source, &mimeType, &confidence, NULL /* format */)) {
-                return 1.0;
-            }
-        }
-
-        if (getDefaultPlayerType() == STAGEFRIGHT_PLAYER) {
-            char buf[20];
-            lseek(fd, offset, SEEK_SET);
-            read(fd, buf, sizeof(buf));
-            lseek(fd, offset, SEEK_SET);
-
-            uint32_t ident = *((uint32_t*)buf);
-
-            // Ogg vorbis?
-            if (ident == 0x5367674f) // 'OggS'
-                return 1.0;
-        }
-
-        return 0.0;
-    }
-
-    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
-                               const char* url,
-                               float /*curScore*/) {
-        if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
-            return 1.0;
-        }
-        return 0.0;
-    }
-
-    virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
-        ALOGV(" create StagefrightPlayer");
-        return new StagefrightPlayer();
-    }
-  private:
-    bool legacyDrm() {
-        char value[PROPERTY_VALUE_MAX];
-        if (property_get("persist.sys.media.legacy-drm", value, NULL)
-                && (!strcmp("1", value) || !strcasecmp("true", value))) {
-            return true;
-        }
-        return false;
-    }
-};
-
 class NuPlayerFactory : public MediaPlayerFactory::IFactory {
   public:
     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
@@ -310,7 +246,6 @@
     if (sInitComplete)
         return;
 
-    registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
     registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
     registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index dda0a57..bb24403 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -57,7 +57,6 @@
 #include <media/MemoryLeakTrackUtil.h>
 #include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/Utils.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooperRoster.h>
@@ -74,7 +73,6 @@
 #include "MediaPlayerFactory.h"
 
 #include "TestPlayerStub.h"
-#include "StagefrightPlayer.h"
 #include "nuplayer/NuPlayerDriver.h"
 
 #include <OMX.h>
@@ -348,6 +346,7 @@
 }
 
 sp<IOMX> MediaPlayerService::getOMX() {
+    ALOGI("MediaPlayerService::getOMX");
     Mutex::Autolock autoLock(mLock);
 
     if (mOMX.get() == NULL) {
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
deleted file mode 100644
index 8fc4b29..0000000
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "StagefrightPlayer"
-#include <utils/Log.h>
-
-#include "StagefrightPlayer.h"
-
-#include "AwesomePlayer.h"
-
-#include <media/Metadata.h>
-#include <media/stagefright/MediaExtractor.h>
-
-namespace android {
-
-StagefrightPlayer::StagefrightPlayer()
-    : mPlayer(new AwesomePlayer) {
-    ALOGV("StagefrightPlayer");
-
-    mPlayer->setListener(this);
-}
-
-StagefrightPlayer::~StagefrightPlayer() {
-    ALOGV("~StagefrightPlayer");
-    reset();
-
-    delete mPlayer;
-    mPlayer = NULL;
-}
-
-status_t StagefrightPlayer::initCheck() {
-    ALOGV("initCheck");
-    return OK;
-}
-
-status_t StagefrightPlayer::setUID(uid_t uid) {
-    mPlayer->setUID(uid);
-
-    return OK;
-}
-
-status_t StagefrightPlayer::setDataSource(
-        const sp<IMediaHTTPService> &httpService,
-        const char *url,
-        const KeyedVector<String8, String8> *headers) {
-    return mPlayer->setDataSource(httpService, url, headers);
-}
-
-// Warning: The filedescriptor passed into this method will only be valid until
-// the method returns, if you want to keep it, dup it!
-status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
-    ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
-    return mPlayer->setDataSource(fd, offset, length);
-}
-
-status_t StagefrightPlayer::setDataSource(const sp<IStreamSource> &source) {
-    return mPlayer->setDataSource(source);
-}
-
-status_t StagefrightPlayer::setVideoSurfaceTexture(
-        const sp<IGraphicBufferProducer> &bufferProducer) {
-    ALOGV("setVideoSurfaceTexture");
-
-    return mPlayer->setSurfaceTexture(bufferProducer);
-}
-
-status_t StagefrightPlayer::prepare() {
-    return mPlayer->prepare();
-}
-
-status_t StagefrightPlayer::prepareAsync() {
-    return mPlayer->prepareAsync();
-}
-
-status_t StagefrightPlayer::start() {
-    ALOGV("start");
-
-    return mPlayer->play();
-}
-
-status_t StagefrightPlayer::stop() {
-    ALOGV("stop");
-
-    return pause();  // what's the difference?
-}
-
-status_t StagefrightPlayer::pause() {
-    ALOGV("pause");
-
-    return mPlayer->pause();
-}
-
-bool StagefrightPlayer::isPlaying() {
-    ALOGV("isPlaying");
-    return mPlayer->isPlaying();
-}
-
-status_t StagefrightPlayer::seekTo(int msec) {
-    ALOGV("seekTo %.2f secs", msec / 1E3);
-
-    status_t err = mPlayer->seekTo((int64_t)msec * 1000);
-
-    return err;
-}
-
-status_t StagefrightPlayer::getCurrentPosition(int *msec) {
-    ALOGV("getCurrentPosition");
-
-    int64_t positionUs;
-    status_t err = mPlayer->getPosition(&positionUs);
-
-    if (err != OK) {
-        return err;
-    }
-
-    *msec = (positionUs + 500) / 1000;
-
-    return OK;
-}
-
-status_t StagefrightPlayer::getDuration(int *msec) {
-    ALOGV("getDuration");
-
-    int64_t durationUs;
-    status_t err = mPlayer->getDuration(&durationUs);
-
-    if (err != OK) {
-        *msec = 0;
-        return OK;
-    }
-
-    *msec = (durationUs + 500) / 1000;
-
-    return OK;
-}
-
-status_t StagefrightPlayer::reset() {
-    ALOGV("reset");
-
-    mPlayer->reset();
-
-    return OK;
-}
-
-status_t StagefrightPlayer::setLooping(int loop) {
-    ALOGV("setLooping");
-
-    return mPlayer->setLooping(loop);
-}
-
-player_type StagefrightPlayer::playerType() {
-    ALOGV("playerType");
-    return STAGEFRIGHT_PLAYER;
-}
-
-status_t StagefrightPlayer::invoke(const Parcel &request, Parcel *reply) {
-    ALOGV("invoke()");
-    return mPlayer->invoke(request, reply);
-}
-
-void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) {
-    MediaPlayerInterface::setAudioSink(audioSink);
-
-    mPlayer->setAudioSink(audioSink);
-}
-
-status_t StagefrightPlayer::setParameter(int key, const Parcel &request) {
-    ALOGV("setParameter(key=%d)", key);
-    return mPlayer->setParameter(key, request);
-}
-
-status_t StagefrightPlayer::getParameter(int key, Parcel *reply) {
-    ALOGV("getParameter");
-    return mPlayer->getParameter(key, reply);
-}
-
-status_t StagefrightPlayer::setPlaybackSettings(const AudioPlaybackRate &rate) {
-    return mPlayer->setPlaybackSettings(rate);
-}
-
-status_t StagefrightPlayer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
-    return mPlayer->getPlaybackSettings(rate);
-}
-
-status_t StagefrightPlayer::getMetadata(
-        const media::Metadata::Filter& /* ids */, Parcel *records) {
-    using media::Metadata;
-
-    uint32_t flags = mPlayer->flags();
-
-    Metadata metadata(records);
-
-    metadata.appendBool(
-            Metadata::kPauseAvailable,
-            flags & MediaExtractor::CAN_PAUSE);
-
-    metadata.appendBool(
-            Metadata::kSeekBackwardAvailable,
-            flags & MediaExtractor::CAN_SEEK_BACKWARD);
-
-    metadata.appendBool(
-            Metadata::kSeekForwardAvailable,
-            flags & MediaExtractor::CAN_SEEK_FORWARD);
-
-    metadata.appendBool(
-            Metadata::kSeekAvailable,
-            flags & MediaExtractor::CAN_SEEK);
-
-    return OK;
-}
-
-status_t StagefrightPlayer::dump(int fd, const Vector<String16> &args) const {
-    return mPlayer->dump(fd, args);
-}
-
-}  // namespace android
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
deleted file mode 100644
index 96013df..0000000
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-**
-** Copyright 2009, 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.
-*/
-
-#ifndef ANDROID_STAGEFRIGHTPLAYER_H
-#define ANDROID_STAGEFRIGHTPLAYER_H
-
-#include <media/MediaPlayerInterface.h>
-
-namespace android {
-
-struct AwesomePlayer;
-
-class StagefrightPlayer : public MediaPlayerInterface {
-public:
-    StagefrightPlayer();
-    virtual ~StagefrightPlayer();
-
-    virtual status_t initCheck();
-
-    virtual status_t setUID(uid_t uid);
-
-    virtual status_t setDataSource(
-            const sp<IMediaHTTPService> &httpService,
-            const char *url,
-            const KeyedVector<String8, String8> *headers);
-
-    virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
-
-    virtual status_t setDataSource(const sp<IStreamSource> &source);
-
-    virtual status_t setVideoSurfaceTexture(
-            const sp<IGraphicBufferProducer> &bufferProducer);
-    virtual status_t prepare();
-    virtual status_t prepareAsync();
-    virtual status_t start();
-    virtual status_t stop();
-    virtual status_t pause();
-    virtual bool isPlaying();
-    virtual status_t seekTo(int msec);
-    virtual status_t getCurrentPosition(int *msec);
-    virtual status_t getDuration(int *msec);
-    virtual status_t reset();
-    virtual status_t setLooping(int loop);
-    virtual player_type playerType();
-    virtual status_t invoke(const Parcel &request, Parcel *reply);
-    virtual void setAudioSink(const sp<AudioSink> &audioSink);
-    virtual status_t setParameter(int key, const Parcel &request);
-    virtual status_t getParameter(int key, Parcel *reply);
-    virtual status_t setPlaybackSettings(const AudioPlaybackRate &rate);
-    virtual status_t getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */);
-
-    virtual status_t getMetadata(
-            const media::Metadata::Filter& ids, Parcel *records);
-
-    virtual status_t dump(int fd, const Vector<String16> &args) const;
-
-private:
-    AwesomePlayer *mPlayer;
-
-    StagefrightPlayer(const StagefrightPlayer &);
-    StagefrightPlayer &operator=(const StagefrightPlayer &);
-};
-
-}  // namespace android
-
-#endif  // ANDROID_STAGEFRIGHTPLAYER_H
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 14a0c66..f297256 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -10,7 +10,6 @@
         AMRWriter.cpp                     \
         AudioPlayer.cpp                   \
         AudioSource.cpp                   \
-        AwesomePlayer.cpp                 \
         CallbackDataSource.cpp            \
         CameraSource.cpp                  \
         CameraSourceTimeLapse.cpp         \
@@ -52,6 +51,7 @@
         ProcessInfo.cpp                   \
         SampleIterator.cpp                \
         SampleTable.cpp                   \
+        SimpleDecodingSource.cpp          \
         SkipCutBuffer.cpp                 \
         StagefrightMediaScanner.cpp       \
         StagefrightMetadataRetriever.cpp  \
@@ -59,7 +59,6 @@
         SurfaceUtils.cpp                  \
         ThrottledSource.cpp               \
         TimeSource.cpp                    \
-        TimedEventQueue.cpp               \
         Utils.cpp                         \
         VBRISeeker.cpp                    \
         VideoFrameScheduler.cpp           \
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index c977958..cb42847 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -33,14 +33,11 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
 
-#include "include/AwesomePlayer.h"
-
 namespace android {
 
 AudioPlayer::AudioPlayer(
         const sp<MediaPlayerBase::AudioSink> &audioSink,
-        uint32_t flags,
-        AwesomePlayer *observer)
+        uint32_t flags)
     : mInputBuffer(NULL),
       mSampleRate(0),
       mLatencyUs(0),
@@ -58,8 +55,6 @@
       mFirstBufferResult(OK),
       mFirstBuffer(NULL),
       mAudioSink(audioSink),
-      mObserver(observer),
-      mPinnedTimeUs(-1ll),
       mPlaying(false),
       mStartPosUs(0),
       mCreateFlags(flags) {
@@ -256,7 +251,6 @@
 
     mStarted = true;
     mPlaying = true;
-    mPinnedTimeUs = -1ll;
 
     return OK;
 }
@@ -279,8 +273,6 @@
         } else {
             mAudioTrack->pause();
         }
-
-        mPinnedTimeUs = ALooper::GetNowUs();
     }
 
     mPlaying = false;
@@ -386,11 +378,6 @@
     static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
 }
 
-bool AudioPlayer::isSeeking() {
-    Mutex::Autolock autoLock(mLock);
-    return mSeeking;
-}
-
 bool AudioPlayer::reachedEOS(status_t *finalStatus) {
     *finalStatus = OK;
 
@@ -399,15 +386,6 @@
     return mReachedEOS;
 }
 
-void AudioPlayer::notifyAudioEOS() {
-    ALOGV("AudioPlayer@0x%p notifyAudioEOS", this);
-
-    if (mObserver != NULL) {
-        mObserver->postAudioEOS(0);
-        ALOGV("Notified observer of EOS!");
-    }
-}
-
 status_t AudioPlayer::setPlaybackRate(const AudioPlaybackRate &rate) {
     if (mAudioSink.get() != NULL) {
         return mAudioSink->setPlaybackRate(rate);
@@ -443,12 +421,10 @@
     case MediaPlayerBase::AudioSink::CB_EVENT_STREAM_END:
         ALOGV("AudioSinkCallback: stream end");
         me->mReachedEOS = true;
-        me->notifyAudioEOS();
         break;
 
     case MediaPlayerBase::AudioSink::CB_EVENT_TEAR_DOWN:
         ALOGV("AudioSinkCallback: Tear down event");
-        me->mObserver->postAudioTearDown();
         break;
     }
 
@@ -467,31 +443,10 @@
 
     case AudioTrack::EVENT_STREAM_END:
         mReachedEOS = true;
-        notifyAudioEOS();
         break;
     }
 }
 
-uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
-    uint32_t numFramesPlayedOut;
-    status_t err;
-
-    if (mAudioSink != NULL) {
-        err = mAudioSink->getPosition(&numFramesPlayedOut);
-    } else {
-        err = mAudioTrack->getPosition(&numFramesPlayedOut);
-    }
-
-    if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
-        return 0;
-    }
-
-    // mNumFramesPlayed is the number of frames submitted
-    // to the audio sink for playback, but not all of them
-    // may have played out by now.
-    return mNumFramesPlayed - numFramesPlayedOut;
-}
-
 size_t AudioPlayer::fillBuffer(void *data, size_t size) {
     if (mNumFramesPlayed == 0) {
         ALOGV("AudioCallback");
@@ -501,10 +456,6 @@
         return 0;
     }
 
-    bool postSeekComplete = false;
-    bool postEOS = false;
-    int64_t postEOSDelayUs = 0;
-
     size_t size_done = 0;
     size_t size_remaining = size;
     while (size_remaining > 0) {
@@ -532,9 +483,6 @@
                 }
 
                 mSeeking = false;
-                if (mObserver) {
-                    postSeekComplete = true;
-                }
             }
         }
 
@@ -567,42 +515,6 @@
                             mAudioTrack->stop();
                         }
                     } else {
-                        if (mObserver) {
-                            // We don't want to post EOS right away but only
-                            // after all frames have actually been played out.
-
-                            // These are the number of frames submitted to the
-                            // AudioTrack that you haven't heard yet.
-                            uint32_t numFramesPendingPlayout =
-                                getNumFramesPendingPlayout();
-
-                            // These are the number of frames we're going to
-                            // submit to the AudioTrack by returning from this
-                            // callback.
-                            uint32_t numAdditionalFrames = size_done / mFrameSize;
-
-                            numFramesPendingPlayout += numAdditionalFrames;
-
-                            int64_t timeToCompletionUs =
-                                (1000000ll * numFramesPendingPlayout) / mSampleRate;
-
-                            ALOGV("total number of frames played: %" PRId64 " (%lld us)",
-                                    (mNumFramesPlayed + numAdditionalFrames),
-                                    1000000ll * (mNumFramesPlayed + numAdditionalFrames)
-                                        / mSampleRate);
-
-                            ALOGV("%d frames left to play, %" PRId64 " us (%.2f secs)",
-                                 numFramesPendingPlayout,
-                                 timeToCompletionUs, timeToCompletionUs / 1E6);
-
-                            postEOS = true;
-                            if (mAudioSink->needsTrailingPadding()) {
-                                postEOSDelayUs = timeToCompletionUs + mLatencyUs;
-                            } else {
-                                postEOSDelayUs = 0;
-                            }
-                        }
-
                         mReachedEOS = true;
                     }
                 }
@@ -626,12 +538,6 @@
             // might not be able to get the exact seek time requested.
             if (refreshSeekTime) {
                 if (useOffload()) {
-                    if (postSeekComplete) {
-                        ALOGV("fillBuffer is going to post SEEK_COMPLETE");
-                        mObserver->postAudioSeekComplete();
-                        postSeekComplete = false;
-                    }
-
                     mStartPosUs = mPositionTimeMediaUs;
                     ALOGV("adjust seek time to: %.2f", mStartPosUs/ 1E6);
                 }
@@ -690,58 +596,11 @@
         Mutex::Autolock autoLock(mLock);
         mNumFramesPlayed += size_done / mFrameSize;
         mNumFramesPlayedSysTimeUs = ALooper::GetNowUs();
-
-        if (mReachedEOS) {
-            mPinnedTimeUs = mNumFramesPlayedSysTimeUs;
-        } else {
-            mPinnedTimeUs = -1ll;
-        }
-    }
-
-    if (postEOS) {
-        mObserver->postAudioEOS(postEOSDelayUs);
-    }
-
-    if (postSeekComplete) {
-        mObserver->postAudioSeekComplete();
     }
 
     return size_done;
 }
 
-int64_t AudioPlayer::getRealTimeUs() {
-    Mutex::Autolock autoLock(mLock);
-    if (useOffload()) {
-        if (mSeeking) {
-            return mSeekTimeUs;
-        }
-        mPositionTimeRealUs = getOutputPlayPositionUs_l();
-        return mPositionTimeRealUs;
-    }
-
-    return getRealTimeUsLocked();
-}
-
-int64_t AudioPlayer::getRealTimeUsLocked() const {
-    CHECK(mStarted);
-    CHECK_NE(mSampleRate, 0);
-    int64_t result = -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
-
-    // Compensate for large audio buffers, updates of mNumFramesPlayed
-    // are less frequent, therefore to get a "smoother" notion of time we
-    // compensate using system time.
-    int64_t diffUs;
-    if (mPinnedTimeUs >= 0ll) {
-        diffUs = mPinnedTimeUs;
-    } else {
-        diffUs = ALooper::GetNowUs();
-    }
-
-    diffUs -= mNumFramesPlayedSysTimeUs;
-
-    return result + diffUs;
-}
-
 int64_t AudioPlayer::getOutputPlayPositionUs_l()
 {
     uint32_t playedSamples = 0;
@@ -770,54 +629,6 @@
     return renderedDuration;
 }
 
-int64_t AudioPlayer::getMediaTimeUs() {
-    Mutex::Autolock autoLock(mLock);
-
-    if (useOffload()) {
-        if (mSeeking) {
-            return mSeekTimeUs;
-        }
-        if (mReachedEOS) {
-            int64_t durationUs;
-            mSource->getFormat()->findInt64(kKeyDuration, &durationUs);
-            return durationUs;
-        }
-        mPositionTimeRealUs = getOutputPlayPositionUs_l();
-        ALOGV("getMediaTimeUs getOutputPlayPositionUs_l() mPositionTimeRealUs %" PRId64,
-              mPositionTimeRealUs);
-        return mPositionTimeRealUs;
-    }
-
-
-    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
-        // mSeekTimeUs is either seek time while seeking or 0 if playback did not start.
-        return mSeekTimeUs;
-    }
-
-    int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
-    if (realTimeOffset < 0) {
-        realTimeOffset = 0;
-    }
-
-    return mPositionTimeMediaUs + realTimeOffset;
-}
-
-bool AudioPlayer::getMediaTimeMapping(
-        int64_t *realtime_us, int64_t *mediatime_us) {
-    Mutex::Autolock autoLock(mLock);
-
-    if (useOffload()) {
-        mPositionTimeRealUs = getOutputPlayPositionUs_l();
-        *realtime_us = mPositionTimeRealUs;
-        *mediatime_us = mPositionTimeRealUs;
-    } else {
-        *realtime_us = mPositionTimeRealUs;
-        *mediatime_us = mPositionTimeMediaUs;
-    }
-
-    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
-}
-
 status_t AudioPlayer::seekTo(int64_t time_us) {
     Mutex::Autolock autoLock(mLock);
 
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
deleted file mode 100644
index f535e5c..0000000
--- a/media/libstagefright/AwesomePlayer.cpp
+++ /dev/null
@@ -1,3077 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#undef DEBUG_HDCP
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "AwesomePlayer"
-#define ATRACE_TAG ATRACE_TAG_VIDEO
-
-#include <inttypes.h>
-
-#include <utils/Log.h>
-#include <utils/Trace.h>
-
-#include <dlfcn.h>
-
-#include "include/AwesomePlayer.h"
-#include "include/DRMExtractor.h"
-#include "include/SoftwareRenderer.h"
-#include "include/NuCachedSource2.h"
-#include "include/ThrottledSource.h"
-#include "include/MPEG2TSExtractor.h"
-#include "include/WVMExtractor.h"
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <media/IMediaHTTPConnection.h>
-#include <media/IMediaHTTPService.h>
-#include <media/IMediaPlayerService.h>
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/timedtext/TimedTextDriver.h>
-#include <media/stagefright/AudioPlayer.h>
-#include <media/stagefright/ClockEstimator.h>
-#include <media/stagefright/DataSource.h>
-#include <media/stagefright/FileSource.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaExtractor.h>
-#include <media/stagefright/MediaHTTP.h>
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/OMXCodec.h>
-#include <media/stagefright/Utils.h>
-
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/Surface.h>
-
-#include <media/stagefright/foundation/AMessage.h>
-
-#include <cutils/properties.h>
-
-#define USE_SURFACE_ALLOC 1
-#define FRAME_DROP_FREQ 0
-#define PROPERTY_OFFLOAD_HIWATERMARK "audio.offload.hiwatermark"
-#define PROPERTY_OFFLOAD_LOWATERMARK "audio.offload.lowatermark"
-
-namespace android {
-
-static int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
-static int64_t kHighWaterMarkUs = 5000000ll;  // 5secs
-static const size_t kLowWaterMarkBytes = 40000;
-static const size_t kHighWaterMarkBytes = 200000;
-static size_t kOffloadLowWaterMarkBytes = kLowWaterMarkBytes;
-static size_t kOffloadHighWaterMarkBytes = kHighWaterMarkBytes;
-// maximum time in paused state when offloading audio decompression. When elapsed, the AudioPlayer
-// is destroyed to allow the audio DSP to power down.
-static int64_t kOffloadPauseMaxUs = 10000000ll;
-
-
-struct AwesomeEvent : public TimedEventQueue::Event {
-    AwesomeEvent(
-            AwesomePlayer *player,
-            void (AwesomePlayer::*method)())
-        : mPlayer(player),
-          mMethod(method) {
-    }
-
-protected:
-    virtual ~AwesomeEvent() {}
-
-    virtual void fire(TimedEventQueue * /* queue */, int64_t /* now_us */) {
-        (mPlayer->*mMethod)();
-    }
-
-private:
-    AwesomePlayer *mPlayer;
-    void (AwesomePlayer::*mMethod)();
-
-    AwesomeEvent(const AwesomeEvent &);
-    AwesomeEvent &operator=(const AwesomeEvent &);
-};
-
-struct AwesomeLocalRenderer : public AwesomeRenderer {
-    AwesomeLocalRenderer(
-            const sp<ANativeWindow> &nativeWindow, const sp<AMessage> &format)
-        : mFormat(format),
-          mTarget(new SoftwareRenderer(nativeWindow)) {
-    }
-
-    virtual void render(MediaBuffer *buffer) {
-        int64_t timeUs;
-        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
-
-        render((const uint8_t *)buffer->data() + buffer->range_offset(),
-               buffer->range_length(), timeUs, timeUs * 1000);
-    }
-
-    void render(const void *data, size_t size, int64_t mediaTimeUs, nsecs_t renderTimeNs) {
-        (void)mTarget->render(data, size, mediaTimeUs, renderTimeNs, NULL, mFormat);
-    }
-
-protected:
-    virtual ~AwesomeLocalRenderer() {
-        delete mTarget;
-        mTarget = NULL;
-    }
-
-private:
-    sp<AMessage> mFormat;
-    SoftwareRenderer *mTarget;
-
-    AwesomeLocalRenderer(const AwesomeLocalRenderer &);
-    AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
-};
-
-struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
-    AwesomeNativeWindowRenderer(
-            const sp<ANativeWindow> &nativeWindow,
-            int32_t rotationDegrees)
-        : mNativeWindow(nativeWindow) {
-        applyRotation(rotationDegrees);
-    }
-
-    virtual void render(MediaBuffer *buffer) {
-        ATRACE_CALL();
-        int64_t timeUs;
-        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
-        native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000);
-        status_t err = mNativeWindow->queueBuffer(
-                mNativeWindow.get(), buffer->graphicBuffer().get(), -1);
-        if (err != 0) {
-            ALOGE("queueBuffer failed with error %s (%d)", strerror(-err),
-                    -err);
-            return;
-        }
-
-        sp<MetaData> metaData = buffer->meta_data();
-        metaData->setInt32(kKeyRendered, 1);
-    }
-
-protected:
-    virtual ~AwesomeNativeWindowRenderer() {}
-
-private:
-    sp<ANativeWindow> mNativeWindow;
-
-    void applyRotation(int32_t rotationDegrees) {
-        uint32_t transform;
-        switch (rotationDegrees) {
-            case 0: transform = 0; break;
-            case 90: transform = HAL_TRANSFORM_ROT_90; break;
-            case 180: transform = HAL_TRANSFORM_ROT_180; break;
-            case 270: transform = HAL_TRANSFORM_ROT_270; break;
-            default: transform = 0; break;
-        }
-
-        if (transform) {
-            CHECK_EQ(0, native_window_set_buffers_transform(
-                        mNativeWindow.get(), transform));
-        }
-    }
-
-    AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
-    AwesomeNativeWindowRenderer &operator=(
-            const AwesomeNativeWindowRenderer &);
-};
-
-// To collect the decoder usage
-void addBatteryData(uint32_t params) {
-    sp<IBinder> binder =
-        defaultServiceManager()->getService(String16("media.player"));
-    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
-    CHECK(service.get() != NULL);
-
-    service->addBatteryData(params);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-AwesomePlayer::AwesomePlayer()
-    : mQueueStarted(false),
-      mUIDValid(false),
-      mTimeSource(NULL),
-      mVideoRenderingStarted(false),
-      mVideoRendererIsPreview(false),
-      mMediaRenderingStartGeneration(0),
-      mStartGeneration(0),
-      mAudioPlayer(NULL),
-      mDisplayWidth(0),
-      mDisplayHeight(0),
-      mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
-      mFlags(0),
-      mExtractorFlags(0),
-      mVideoBuffer(NULL),
-      mDecryptHandle(NULL),
-      mLastVideoTimeUs(-1),
-      mTextDriver(NULL),
-      mSelectedTimedTextTrack(-1),
-      mOffloadAudio(false),
-      mAudioTearDown(false) {
-    CHECK_EQ(mClient.connect(), (status_t)OK);
-
-    DataSource::RegisterDefaultSniffers();
-
-    mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
-    mVideoEventPending = false;
-    mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
-    mStreamDoneEventPending = false;
-    mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
-    mBufferingEventPending = false;
-    mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
-    mVideoLagEventPending = false;
-
-    mCheckAudioStatusEvent = new AwesomeEvent(
-            this, &AwesomePlayer::onCheckAudioStatus);
-
-    mAudioStatusEventPending = false;
-
-    mAudioTearDownEvent = new AwesomeEvent(this,
-                              &AwesomePlayer::onAudioTearDownEvent);
-    mAudioTearDownEventPending = false;
-
-    mClockEstimator = new WindowedLinearFitEstimator();
-
-    mPlaybackSettings = AUDIO_PLAYBACK_RATE_DEFAULT;
-
-    reset();
-}
-
-AwesomePlayer::~AwesomePlayer() {
-    if (mQueueStarted) {
-        mQueue.stop();
-    }
-
-    reset();
-
-    mClient.disconnect();
-}
-
-void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) {
-    mQueue.cancelEvent(mVideoEvent->eventID());
-    mVideoEventPending = false;
-    mQueue.cancelEvent(mVideoLagEvent->eventID());
-    mVideoLagEventPending = false;
-
-    if (mOffloadAudio) {
-        mQueue.cancelEvent(mAudioTearDownEvent->eventID());
-        mAudioTearDownEventPending = false;
-    }
-
-    if (!keepNotifications) {
-        mQueue.cancelEvent(mStreamDoneEvent->eventID());
-        mStreamDoneEventPending = false;
-        mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
-        mAudioStatusEventPending = false;
-
-        mQueue.cancelEvent(mBufferingEvent->eventID());
-        mBufferingEventPending = false;
-        mAudioTearDown = false;
-    }
-}
-
-void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
-    Mutex::Autolock autoLock(mLock);
-    mListener = listener;
-}
-
-void AwesomePlayer::setUID(uid_t uid) {
-    ALOGV("AwesomePlayer running on behalf of uid %d", uid);
-
-    mUID = uid;
-    mUIDValid = true;
-}
-
-status_t AwesomePlayer::setDataSource(
-        const sp<IMediaHTTPService> &httpService,
-        const char *uri,
-        const KeyedVector<String8, String8> *headers) {
-    Mutex::Autolock autoLock(mLock);
-    return setDataSource_l(httpService, uri, headers);
-}
-
-status_t AwesomePlayer::setDataSource_l(
-        const sp<IMediaHTTPService> &httpService,
-        const char *uri,
-        const KeyedVector<String8, String8> *headers) {
-    reset_l();
-
-    mHTTPService = httpService;
-    mUri = uri;
-
-    if (headers) {
-        mUriHeaders = *headers;
-
-        ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
-        if (index >= 0) {
-            // Browser is in "incognito" mode, suppress logging URLs.
-
-            // This isn't something that should be passed to the server.
-            mUriHeaders.removeItemsAt(index);
-
-            modifyFlags(INCOGNITO, SET);
-        }
-    }
-
-    ALOGI("setDataSource_l(%s)", uriDebugString(mUri, mFlags & INCOGNITO).c_str());
-
-    // The actual work will be done during preparation in the call to
-    // ::finishSetDataSource_l to avoid blocking the calling thread in
-    // setDataSource for any significant time.
-
-    {
-        Mutex::Autolock autoLock(mStatsLock);
-        mStats.mFd = -1;
-        mStats.mURI = mUri;
-    }
-
-    return OK;
-}
-
-status_t AwesomePlayer::setDataSource(
-        int fd, int64_t offset, int64_t length) {
-    Mutex::Autolock autoLock(mLock);
-
-    reset_l();
-
-    fd = dup(fd);
-    sp<DataSource> dataSource = new FileSource(fd, offset, length);
-
-    status_t err = dataSource->initCheck();
-
-    if (err != OK) {
-        return err;
-    }
-
-    mFileSource = dataSource;
-
-    {
-        Mutex::Autolock autoLock(mStatsLock);
-        mStats.mFd = fd;
-        mStats.mURI = String8();
-    }
-
-    return setDataSource_l(dataSource);
-}
-
-status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source __unused) {
-    return INVALID_OPERATION;
-}
-
-status_t AwesomePlayer::setDataSource_l(
-        const sp<DataSource> &dataSource) {
-    sp<IMediaExtractor> extractor = MediaExtractor::Create(dataSource);
-
-    if (extractor == NULL) {
-        return UNKNOWN_ERROR;
-    }
-
-    if (extractor->getDrmFlag()) {
-        checkDrmStatus(dataSource);
-    }
-
-    return setDataSource_l(extractor);
-}
-
-void AwesomePlayer::checkDrmStatus(const sp<DataSource>& dataSource) {
-    dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
-    if (mDecryptHandle != NULL) {
-        CHECK(mDrmManagerClient);
-        if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
-            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
-        }
-    }
-}
-
-status_t AwesomePlayer::setDataSource_l(const sp<IMediaExtractor> &extractor) {
-    // Attempt to approximate overall stream bitrate by summing all
-    // tracks' individual bitrates, if not all of them advertise bitrate,
-    // we have to fail.
-
-    int64_t totalBitRate = 0;
-
-    mExtractor = extractor;
-    for (size_t i = 0; i < extractor->countTracks(); ++i) {
-        sp<MetaData> meta = extractor->getTrackMetaData(i);
-
-        int32_t bitrate;
-        if (!meta->findInt32(kKeyBitRate, &bitrate)) {
-            const char *mime;
-            CHECK(meta->findCString(kKeyMIMEType, &mime));
-            ALOGV("track of type '%s' does not publish bitrate", mime);
-
-            totalBitRate = -1;
-            break;
-        }
-
-        totalBitRate += bitrate;
-    }
-    sp<MetaData> fileMeta = mExtractor->getMetaData();
-    if (fileMeta != NULL) {
-        int64_t duration;
-        if (fileMeta->findInt64(kKeyDuration, &duration)) {
-            mDurationUs = duration;
-        }
-    }
-
-    mBitrate = totalBitRate;
-
-    ALOGV("mBitrate = %lld bits/sec", (long long)mBitrate);
-
-    {
-        Mutex::Autolock autoLock(mStatsLock);
-        mStats.mBitrate = mBitrate;
-        mStats.mTracks.clear();
-        mStats.mAudioTrackIndex = -1;
-        mStats.mVideoTrackIndex = -1;
-    }
-
-    bool haveAudio = false;
-    bool haveVideo = false;
-    for (size_t i = 0; i < extractor->countTracks(); ++i) {
-        sp<MetaData> meta = extractor->getTrackMetaData(i);
-
-        const char *_mime;
-        CHECK(meta->findCString(kKeyMIMEType, &_mime));
-
-        String8 mime = String8(_mime);
-
-        if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) {
-            setVideoSource(extractor->getTrack(i));
-            haveVideo = true;
-
-            // Set the presentation/display size
-            int32_t displayWidth, displayHeight;
-            bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
-            if (success) {
-                success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
-            }
-            if (success) {
-                mDisplayWidth = displayWidth;
-                mDisplayHeight = displayHeight;
-            }
-
-            {
-                Mutex::Autolock autoLock(mStatsLock);
-                mStats.mVideoTrackIndex = mStats.mTracks.size();
-                mStats.mTracks.push();
-                TrackStat *stat =
-                    &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
-                stat->mMIME = mime.string();
-            }
-        } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
-            setAudioSource(extractor->getTrack(i));
-            haveAudio = true;
-            mActiveAudioTrackIndex = i;
-
-            {
-                Mutex::Autolock autoLock(mStatsLock);
-                mStats.mAudioTrackIndex = mStats.mTracks.size();
-                mStats.mTracks.push();
-                TrackStat *stat =
-                    &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
-                stat->mMIME = mime.string();
-            }
-
-            if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_AUDIO_VORBIS)) {
-                // Only do this for vorbis audio, none of the other audio
-                // formats even support this ringtone specific hack and
-                // retrieving the metadata on some extractors may turn out
-                // to be very expensive.
-                sp<MetaData> fileMeta = extractor->getMetaData();
-                int32_t loop;
-                if (fileMeta != NULL
-                        && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
-                    modifyFlags(AUTO_LOOPING, SET);
-                }
-            }
-        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
-            addTextSource_l(i, extractor->getTrack(i));
-        }
-    }
-
-    if (!haveAudio && !haveVideo) {
-        if (mWVMExtractor != NULL) {
-            return mWVMExtractor->getError();
-        } else {
-            return UNKNOWN_ERROR;
-        }
-    }
-
-    mExtractorFlags = extractor->flags();
-
-    return OK;
-}
-
-void AwesomePlayer::reset() {
-    Mutex::Autolock autoLock(mLock);
-    reset_l();
-}
-
-void AwesomePlayer::reset_l() {
-    mVideoRenderingStarted = false;
-    mActiveAudioTrackIndex = -1;
-    mDisplayWidth = 0;
-    mDisplayHeight = 0;
-
-    notifyListener_l(MEDIA_STOPPED);
-
-    if (mDecryptHandle != NULL) {
-            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
-                    Playback::STOP, 0);
-            mDecryptHandle = NULL;
-            mDrmManagerClient = NULL;
-    }
-
-    if (mFlags & PLAYING) {
-        uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
-        if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
-            params |= IMediaPlayerService::kBatteryDataTrackAudio;
-        }
-        if (mVideoSource != NULL) {
-            params |= IMediaPlayerService::kBatteryDataTrackVideo;
-        }
-        addBatteryData(params);
-    }
-
-    if (mFlags & PREPARING) {
-        modifyFlags(PREPARE_CANCELLED, SET);
-        if (mConnectingDataSource != NULL) {
-            ALOGI("interrupting the connection process");
-            mConnectingDataSource->disconnect();
-        }
-
-        if (mFlags & PREPARING_CONNECTED) {
-            // We are basically done preparing, we're just buffering
-            // enough data to start playback, we can safely interrupt that.
-            finishAsyncPrepare_l();
-        }
-    }
-
-    while (mFlags & PREPARING) {
-        mPreparedCondition.wait(mLock);
-    }
-
-    cancelPlayerEvents();
-
-    mWVMExtractor.clear();
-    mCachedSource.clear();
-    mAudioTrack.clear();
-    mVideoTrack.clear();
-    mExtractor.clear();
-
-    // Shutdown audio first, so that the response to the reset request
-    // appears to happen instantaneously as far as the user is concerned
-    // If we did this later, audio would continue playing while we
-    // shutdown the video-related resources and the player appear to
-    // not be as responsive to a reset request.
-    if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
-            && mAudioSource != NULL) {
-        // If we had an audio player, it would have effectively
-        // taken possession of the audio source and stopped it when
-        // _it_ is stopped. Otherwise this is still our responsibility.
-        mAudioSource->stop();
-    }
-    mAudioSource.clear();
-    mOmxSource.clear();
-
-    mTimeSource = NULL;
-
-    delete mAudioPlayer;
-    mAudioPlayer = NULL;
-
-    if (mTextDriver != NULL) {
-        delete mTextDriver;
-        mTextDriver = NULL;
-    }
-
-    mVideoRenderer.clear();
-
-    if (mVideoSource != NULL) {
-        shutdownVideoDecoder_l();
-    }
-
-    mDurationUs = -1;
-    modifyFlags(0, ASSIGN);
-    mExtractorFlags = 0;
-    mTimeSourceDeltaUs = 0;
-    mVideoTimeUs = 0;
-
-    mSeeking = NO_SEEK;
-    mSeekNotificationSent = true;
-    mSeekTimeUs = 0;
-
-    mHTTPService.clear();
-    mUri.setTo("");
-    mUriHeaders.clear();
-
-    mFileSource.clear();
-
-    mBitrate = -1;
-    mLastVideoTimeUs = -1;
-
-    {
-        Mutex::Autolock autoLock(mStatsLock);
-        mStats.mFd = -1;
-        mStats.mURI = String8();
-        mStats.mBitrate = -1;
-        mStats.mAudioTrackIndex = -1;
-        mStats.mVideoTrackIndex = -1;
-        mStats.mNumVideoFramesDecoded = 0;
-        mStats.mNumVideoFramesDropped = 0;
-        mStats.mVideoWidth = -1;
-        mStats.mVideoHeight = -1;
-        mStats.mFlags = 0;
-        mStats.mTracks.clear();
-    }
-
-    mWatchForAudioSeekComplete = false;
-    mWatchForAudioEOS = false;
-
-    mMediaRenderingStartGeneration = 0;
-    mStartGeneration = 0;
-
-    kOffloadLowWaterMarkBytes =
-        property_get_int32(PROPERTY_OFFLOAD_LOWATERMARK, kLowWaterMarkBytes);
-    kOffloadHighWaterMarkBytes =
-        property_get_int32(PROPERTY_OFFLOAD_HIWATERMARK, kHighWaterMarkBytes);
-}
-
-void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
-    if ((mListener != NULL) && !mAudioTearDown) {
-        sp<MediaPlayerBase> listener = mListener.promote();
-
-        if (listener != NULL) {
-            listener->sendEvent(msg, ext1, ext2);
-        }
-    }
-}
-
-bool AwesomePlayer::getBitrate(int64_t *bitrate) {
-    off64_t size;
-    if (mDurationUs > 0 && mCachedSource != NULL
-            && mCachedSource->getSize(&size) == OK) {
-        *bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
-        return true;
-    }
-
-    if (mBitrate >= 0) {
-        *bitrate = mBitrate;
-        return true;
-    }
-
-    *bitrate = 0;
-
-    return false;
-}
-
-// Returns true iff cached duration is available/applicable.
-bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
-    int64_t bitrate;
-
-    if (mCachedSource != NULL && getBitrate(&bitrate) && (bitrate > 0)) {
-        status_t finalStatus;
-        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
-        *durationUs = cachedDataRemaining * 8000000ll / bitrate;
-        *eos = (finalStatus != OK);
-        return true;
-    } else if (mWVMExtractor != NULL) {
-        status_t finalStatus;
-        *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
-        *eos = (finalStatus != OK);
-        return true;
-    }
-
-    return false;
-}
-
-void AwesomePlayer::ensureCacheIsFetching_l() {
-    if (mCachedSource != NULL) {
-        mCachedSource->resumeFetchingIfNecessary();
-    }
-}
-
-void AwesomePlayer::onVideoLagUpdate() {
-    Mutex::Autolock autoLock(mLock);
-    if (!mVideoLagEventPending) {
-        return;
-    }
-    mVideoLagEventPending = false;
-
-    int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
-    int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
-
-    if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
-        ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
-
-        notifyListener_l(
-                MEDIA_INFO,
-                MEDIA_INFO_VIDEO_TRACK_LAGGING,
-                videoLateByUs / 1000ll);
-    }
-
-    postVideoLagEvent_l();
-}
-
-void AwesomePlayer::onBufferingUpdate() {
-    Mutex::Autolock autoLock(mLock);
-    if (!mBufferingEventPending) {
-        return;
-    }
-    mBufferingEventPending = false;
-
-    if (mCachedSource != NULL) {
-        status_t finalStatus;
-        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
-        bool eos = (finalStatus != OK);
-
-        ALOGV("cachedDataRemaining = %zu b, eos=%d", cachedDataRemaining, eos);
-        if (eos) {
-            if (finalStatus == ERROR_END_OF_STREAM) {
-                notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
-            }
-            if (mFlags & PREPARING) {
-                ALOGV("cache has reached EOS, prepare is done.");
-                finishAsyncPrepare_l();
-            }
-        } else {
-            bool eos2;
-            bool knownDuration = false;
-            int64_t cachedDurationUs;
-            if (getCachedDuration_l(&cachedDurationUs, &eos2) && mDurationUs > 0) {
-                knownDuration = true;
-                int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
-                if (percentage > 100) {
-                    percentage = 100;
-                }
-
-                notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
-            }
-            if (!knownDuration || mOffloadAudio) {
-                // If we don't know the bitrate/duration of the stream, or are offloading
-                // decode, use absolute size limits to maintain the cache.
-
-                size_t lowWatermark =
-                        mOffloadAudio ? kOffloadLowWaterMarkBytes : kLowWaterMarkBytes;
-                size_t highWatermark =
-                        mOffloadAudio ? kOffloadHighWaterMarkBytes : kHighWaterMarkBytes;
-
-                if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) {
-                    ALOGI("cache is running low (< %zu) , pausing.", lowWatermark);
-                    modifyFlags(CACHE_UNDERRUN, SET);
-                    pause_l();
-                    ensureCacheIsFetching_l();
-                    sendCacheStats();
-                    notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
-                } else if (eos || cachedDataRemaining > highWatermark) {
-                    if (mFlags & CACHE_UNDERRUN) {
-                        ALOGI("cache has filled up (> %zu), resuming.",
-                             highWatermark);
-                        modifyFlags(CACHE_UNDERRUN, CLEAR);
-                        play_l();
-                    } else if (mFlags & PREPARING) {
-                        ALOGV("cache has filled up (> %zu), prepare is done",
-                             highWatermark);
-                        finishAsyncPrepare_l();
-                    }
-                }
-            }
-        }
-    } else if (mWVMExtractor != NULL) {
-        status_t finalStatus;
-
-        int64_t cachedDurationUs
-            = mWVMExtractor->getCachedDurationUs(&finalStatus);
-
-        bool eos = (finalStatus != OK);
-
-        if (eos) {
-            if (finalStatus == ERROR_END_OF_STREAM) {
-                notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
-            }
-            if (mFlags & PREPARING) {
-                ALOGV("cache has reached EOS, prepare is done.");
-                finishAsyncPrepare_l();
-            }
-        } else {
-            int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
-            if (percentage > 100) {
-                percentage = 100;
-            }
-
-            notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
-        }
-    }
-
-    int64_t cachedDurationUs;
-    bool eos;
-    if (!mOffloadAudio && getCachedDuration_l(&cachedDurationUs, &eos)) {
-        ALOGV("cachedDurationUs = %.2f secs, eos=%d",
-             cachedDurationUs / 1E6, eos);
-
-        if ((mFlags & PLAYING) && !eos
-                && (cachedDurationUs < kLowWaterMarkUs)) {
-            modifyFlags(CACHE_UNDERRUN, SET);
-            ALOGI("cache is running low (%.2f secs) , pausing.",
-                  cachedDurationUs / 1E6);
-            pause_l();
-            ensureCacheIsFetching_l();
-            sendCacheStats();
-            notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
-        } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
-            if (mFlags & CACHE_UNDERRUN) {
-                modifyFlags(CACHE_UNDERRUN, CLEAR);
-                ALOGI("cache has filled up (%.2f secs), resuming.",
-                      cachedDurationUs / 1E6);
-                play_l();
-            } else if (mFlags & PREPARING) {
-                ALOGV("cache has filled up (%.2f secs), prepare is done",
-                     cachedDurationUs / 1E6);
-                finishAsyncPrepare_l();
-            }
-        }
-    }
-
-    if ( ((mFlags & PLAYING) && !eos) ||
-         (mFlags & (PREPARING | CACHE_UNDERRUN)) ) {
-        postBufferingEvent_l();
-    }
-}
-
-void AwesomePlayer::sendCacheStats() {
-    sp<MediaPlayerBase> listener = mListener.promote();
-    if (listener != NULL) {
-        int32_t kbps = 0;
-        status_t err = UNKNOWN_ERROR;
-        if (mCachedSource != NULL) {
-            err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
-        } else if (mWVMExtractor != NULL) {
-            err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps);
-        }
-        if (err == OK) {
-            listener->sendEvent(
-                MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
-        }
-    }
-}
-
-void AwesomePlayer::onStreamDone() {
-    // Posted whenever any stream finishes playing.
-    ATRACE_CALL();
-
-    Mutex::Autolock autoLock(mLock);
-    if (!mStreamDoneEventPending) {
-        return;
-    }
-    mStreamDoneEventPending = false;
-
-    if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
-        ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
-
-        notifyListener_l(
-                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
-
-        pause_l(true /* at eos */);
-
-        modifyFlags(AT_EOS, SET);
-        return;
-    }
-
-    const bool allDone =
-        (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
-            && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
-
-    if (!allDone) {
-        return;
-    }
-
-    if (mFlags & AUTO_LOOPING) {
-        audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
-        if (mAudioSink != NULL) {
-            streamType = mAudioSink->getAudioStreamType();
-        }
-        if (streamType == AUDIO_STREAM_NOTIFICATION) {
-            ALOGW("disabling auto-loop for notification");
-            modifyFlags(AUTO_LOOPING, CLEAR);
-        }
-    }
-    if ((mFlags & LOOPING)
-            || (mFlags & AUTO_LOOPING)) {
-
-        seekTo_l(0);
-
-        if (mVideoSource != NULL) {
-            postVideoEvent_l();
-        }
-    } else {
-        ALOGV("MEDIA_PLAYBACK_COMPLETE");
-        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
-
-        pause_l(true /* at eos */);
-
-        // If audio hasn't completed MEDIA_SEEK_COMPLETE yet,
-        // notify MEDIA_SEEK_COMPLETE to observer immediately for state persistence.
-        if (mWatchForAudioSeekComplete) {
-            notifyListener_l(MEDIA_SEEK_COMPLETE);
-            mWatchForAudioSeekComplete = false;
-        }
-
-        modifyFlags(AT_EOS, SET);
-    }
-}
-
-status_t AwesomePlayer::play() {
-    ATRACE_CALL();
-
-    Mutex::Autolock autoLock(mLock);
-
-    modifyFlags(CACHE_UNDERRUN, CLEAR);
-
-    return play_l();
-}
-
-status_t AwesomePlayer::play_l() {
-    modifyFlags(SEEK_PREVIEW, CLEAR);
-
-    if (mFlags & PLAYING) {
-        return OK;
-    }
-
-    mMediaRenderingStartGeneration = ++mStartGeneration;
-
-    if (!(mFlags & PREPARED)) {
-        status_t err = prepare_l();
-
-        if (err != OK) {
-            return err;
-        }
-    }
-
-    modifyFlags(PLAYING, SET);
-    modifyFlags(FIRST_FRAME, SET);
-
-    if (mDecryptHandle != NULL) {
-        int64_t position;
-        getPosition(&position);
-        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
-                Playback::START, position / 1000);
-    }
-
-    if (mAudioSource != NULL) {
-        if (mAudioPlayer == NULL) {
-            createAudioPlayer_l();
-        }
-
-        CHECK(!(mFlags & AUDIO_RUNNING));
-
-        if (mVideoSource == NULL) {
-
-            // We don't want to post an error notification at this point,
-            // the error returned from MediaPlayer::start() will suffice.
-
-            status_t err = startAudioPlayer_l(
-                    false /* sendErrorNotification */);
-
-            if ((err != OK) && mOffloadAudio) {
-                ALOGI("play_l() cannot create offload output, fallback to sw decode");
-                int64_t curTimeUs;
-                getPosition(&curTimeUs);
-
-                delete mAudioPlayer;
-                mAudioPlayer = NULL;
-                // if the player was started it will take care of stopping the source when destroyed
-                if (!(mFlags & AUDIOPLAYER_STARTED)) {
-                    mAudioSource->stop();
-                }
-                modifyFlags((AUDIO_RUNNING | AUDIOPLAYER_STARTED), CLEAR);
-                mOffloadAudio = false;
-                mAudioSource = mOmxSource;
-                if (mAudioSource != NULL) {
-                    err = mAudioSource->start();
-
-                    if (err != OK) {
-                        mAudioSource.clear();
-                    } else {
-                        mSeekNotificationSent = true;
-                        if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
-                            seekTo_l(curTimeUs);
-                        }
-                        createAudioPlayer_l();
-                        err = startAudioPlayer_l(false);
-                    }
-                }
-            }
-
-            if (err != OK) {
-                delete mAudioPlayer;
-                mAudioPlayer = NULL;
-
-                modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
-
-                if (mDecryptHandle != NULL) {
-                    mDrmManagerClient->setPlaybackStatus(
-                            mDecryptHandle, Playback::STOP, 0);
-                }
-
-                return err;
-            }
-        }
-
-        if (mAudioPlayer != NULL) {
-            mAudioPlayer->setPlaybackRate(mPlaybackSettings);
-        }
-    }
-
-    if (mTimeSource == NULL && mAudioPlayer == NULL) {
-        mTimeSource = &mSystemTimeSource;
-    }
-
-    if (mVideoSource != NULL) {
-        // Kick off video playback
-        postVideoEvent_l();
-
-        if (mAudioSource != NULL && mVideoSource != NULL) {
-            postVideoLagEvent_l();
-        }
-    }
-
-    if (mFlags & AT_EOS) {
-        // Legacy behaviour, if a stream finishes playing and then
-        // is started again, we play from the start...
-        seekTo_l(0);
-    }
-
-    uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
-        | IMediaPlayerService::kBatteryDataTrackDecoder;
-    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
-        params |= IMediaPlayerService::kBatteryDataTrackAudio;
-    }
-    if (mVideoSource != NULL) {
-        params |= IMediaPlayerService::kBatteryDataTrackVideo;
-    }
-    addBatteryData(params);
-
-    if (isStreamingHTTP()) {
-        postBufferingEvent_l();
-    }
-
-    return OK;
-}
-
-void AwesomePlayer::createAudioPlayer_l()
-{
-    uint32_t flags = 0;
-    int64_t cachedDurationUs;
-    bool eos;
-
-    if (mOffloadAudio) {
-        flags |= AudioPlayer::USE_OFFLOAD;
-    } else if (mVideoSource == NULL
-            && (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US ||
-            (getCachedDuration_l(&cachedDurationUs, &eos) &&
-            cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) {
-        flags |= AudioPlayer::ALLOW_DEEP_BUFFERING;
-    }
-    if (isStreamingHTTP()) {
-        flags |= AudioPlayer::IS_STREAMING;
-    }
-    if (mVideoSource != NULL) {
-        flags |= AudioPlayer::HAS_VIDEO;
-    }
-
-    mAudioPlayer = new AudioPlayer(mAudioSink, flags, this);
-    mAudioPlayer->setSource(mAudioSource);
-
-    mTimeSource = mAudioPlayer;
-
-    // If there was a seek request before we ever started,
-    // honor the request now.
-    // Make sure to do this before starting the audio player
-    // to avoid a race condition.
-    seekAudioIfNecessary_l();
-}
-
-void AwesomePlayer::notifyIfMediaStarted_l() {
-    if (mMediaRenderingStartGeneration == mStartGeneration) {
-        mMediaRenderingStartGeneration = -1;
-        notifyListener_l(MEDIA_STARTED);
-    }
-}
-
-status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
-    CHECK(!(mFlags & AUDIO_RUNNING));
-    status_t err = OK;
-
-    if (mAudioSource == NULL || mAudioPlayer == NULL) {
-        return OK;
-    }
-
-    if (mOffloadAudio) {
-        mQueue.cancelEvent(mAudioTearDownEvent->eventID());
-        mAudioTearDownEventPending = false;
-    }
-
-    if (!(mFlags & AUDIOPLAYER_STARTED)) {
-        bool wasSeeking = mAudioPlayer->isSeeking();
-
-        // We've already started the MediaSource in order to enable
-        // the prefetcher to read its data.
-        err = mAudioPlayer->start(
-                true /* sourceAlreadyStarted */);
-
-        if (err != OK) {
-            if (sendErrorNotification) {
-                notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
-            }
-
-            return err;
-        }
-
-        modifyFlags(AUDIOPLAYER_STARTED, SET);
-
-        if (wasSeeking) {
-            CHECK(!mAudioPlayer->isSeeking());
-
-            // We will have finished the seek while starting the audio player.
-            postAudioSeekComplete();
-        } else {
-            notifyIfMediaStarted_l();
-        }
-    } else {
-        err = mAudioPlayer->resume();
-    }
-
-    if (err == OK) {
-        err = mAudioPlayer->setPlaybackRate(mPlaybackSettings);
-    }
-
-    if (err == OK) {
-        modifyFlags(AUDIO_RUNNING, SET);
-
-        mWatchForAudioEOS = true;
-    }
-
-    return err;
-}
-
-void AwesomePlayer::notifyVideoSize_l() {
-    ATRACE_CALL();
-    sp<MetaData> meta = mVideoSource->getFormat();
-
-    int32_t cropLeft, cropTop, cropRight, cropBottom;
-    if (!meta->findRect(
-                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
-        int32_t width, height;
-        CHECK(meta->findInt32(kKeyWidth, &width));
-        CHECK(meta->findInt32(kKeyHeight, &height));
-
-        cropLeft = cropTop = 0;
-        cropRight = width - 1;
-        cropBottom = height - 1;
-
-        ALOGV("got dimensions only %d x %d", width, height);
-    } else {
-        ALOGV("got crop rect %d, %d, %d, %d",
-             cropLeft, cropTop, cropRight, cropBottom);
-    }
-
-    int32_t displayWidth;
-    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
-        ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
-        mDisplayWidth = displayWidth;
-    }
-    int32_t displayHeight;
-    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
-        ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
-        mDisplayHeight = displayHeight;
-    }
-
-    int32_t usableWidth = cropRight - cropLeft + 1;
-    int32_t usableHeight = cropBottom - cropTop + 1;
-    if (mDisplayWidth != 0) {
-        usableWidth = mDisplayWidth;
-    }
-    if (mDisplayHeight != 0) {
-        usableHeight = mDisplayHeight;
-    }
-
-    {
-        Mutex::Autolock autoLock(mStatsLock);
-        mStats.mVideoWidth = usableWidth;
-        mStats.mVideoHeight = usableHeight;
-    }
-
-    int32_t rotationDegrees;
-    if (!mVideoTrack->getFormat()->findInt32(
-                kKeyRotation, &rotationDegrees)) {
-        rotationDegrees = 0;
-    }
-
-    if (rotationDegrees == 90 || rotationDegrees == 270) {
-        notifyListener_l(
-                MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
-    } else {
-        notifyListener_l(
-                MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
-    }
-}
-
-void AwesomePlayer::initRenderer_l() {
-    ATRACE_CALL();
-
-    if (mNativeWindow == NULL) {
-        return;
-    }
-
-    sp<MetaData> meta = mVideoSource->getFormat();
-
-    int32_t format;
-    const char *component;
-    int32_t decodedWidth, decodedHeight;
-    CHECK(meta->findInt32(kKeyColorFormat, &format));
-    CHECK(meta->findCString(kKeyDecoderComponent, &component));
-    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
-    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
-
-    int32_t rotationDegrees;
-    if (!mVideoTrack->getFormat()->findInt32(
-                kKeyRotation, &rotationDegrees)) {
-        rotationDegrees = 0;
-    }
-
-    mVideoRenderer.clear();
-
-    // Must ensure that mVideoRenderer's destructor is actually executed
-    // before creating a new one.
-    IPCThreadState::self()->flushCommands();
-
-    // Even if set scaling mode fails, we will continue anyway
-    setVideoScalingMode_l(mVideoScalingMode);
-    if (USE_SURFACE_ALLOC
-            && !strncmp(component, "OMX.", 4)
-            && strncmp(component, "OMX.google.", 11)) {
-        // Hardware decoders avoid the CPU color conversion by decoding
-        // directly to ANativeBuffers, so we must use a renderer that
-        // just pushes those buffers to the ANativeWindow.
-        mVideoRenderer =
-            new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
-    } else {
-        // Other decoders are instantiated locally and as a consequence
-        // allocate their buffers in local address space.  This renderer
-        // then performs a color conversion and copy to get the data
-        // into the ANativeBuffer.
-        sp<AMessage> format;
-        CHECK(OK == convertMetaDataToMessage(meta, &format));
-        mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, format);
-    }
-}
-
-status_t AwesomePlayer::pause() {
-    ATRACE_CALL();
-
-    Mutex::Autolock autoLock(mLock);
-
-    modifyFlags(CACHE_UNDERRUN, CLEAR);
-
-    return pause_l();
-}
-
-status_t AwesomePlayer::pause_l(bool at_eos) {
-    if (!(mFlags & PLAYING)) {
-        if (mAudioTearDown && mAudioTearDownWasPlaying) {
-            ALOGV("pause_l() during teardown and finishSetDataSource_l() mFlags %x" , mFlags);
-            mAudioTearDownWasPlaying = false;
-            notifyListener_l(MEDIA_PAUSED);
-            mMediaRenderingStartGeneration = ++mStartGeneration;
-        }
-        return OK;
-    }
-
-    notifyListener_l(MEDIA_PAUSED);
-    mMediaRenderingStartGeneration = ++mStartGeneration;
-
-    cancelPlayerEvents(true /* keepNotifications */);
-
-    if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
-        // If we played the audio stream to completion we
-        // want to make sure that all samples remaining in the audio
-        // track's queue are played out.
-        mAudioPlayer->pause(at_eos /* playPendingSamples */);
-        // send us a reminder to tear down the AudioPlayer if paused for too long.
-        if (mOffloadAudio) {
-            postAudioTearDownEvent(kOffloadPauseMaxUs);
-        }
-        modifyFlags(AUDIO_RUNNING, CLEAR);
-    }
-
-    if (mFlags & TEXTPLAYER_INITIALIZED) {
-        mTextDriver->pause();
-        modifyFlags(TEXT_RUNNING, CLEAR);
-    }
-
-    modifyFlags(PLAYING, CLEAR);
-
-    if (mDecryptHandle != NULL) {
-        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
-                Playback::PAUSE, 0);
-    }
-
-    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
-    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
-        params |= IMediaPlayerService::kBatteryDataTrackAudio;
-    }
-    if (mVideoSource != NULL) {
-        params |= IMediaPlayerService::kBatteryDataTrackVideo;
-    }
-
-    addBatteryData(params);
-
-    return OK;
-}
-
-bool AwesomePlayer::isPlaying() const {
-    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
-}
-
-status_t AwesomePlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) {
-    Mutex::Autolock autoLock(mLock);
-
-    status_t err;
-    if (bufferProducer != NULL) {
-        err = setNativeWindow_l(new Surface(bufferProducer));
-    } else {
-        err = setNativeWindow_l(NULL);
-    }
-
-    return err;
-}
-
-void AwesomePlayer::shutdownVideoDecoder_l() {
-    if (mVideoBuffer) {
-        mVideoBuffer->release();
-        mVideoBuffer = NULL;
-    }
-
-    mVideoSource->stop();
-
-    // The following hack is necessary to ensure that the OMX
-    // component is completely released by the time we may try
-    // to instantiate it again.
-    wp<IMediaSource> tmp = mVideoSource;
-    mVideoSource.clear();
-    while (tmp.promote() != NULL) {
-        usleep(1000);
-    }
-    IPCThreadState::self()->flushCommands();
-    ALOGV("video decoder shutdown completed");
-}
-
-status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
-    mNativeWindow = native;
-
-    if (mVideoSource == NULL) {
-        return OK;
-    }
-
-    ALOGV("attempting to reconfigure to use new surface");
-
-    bool wasPlaying = (mFlags & PLAYING) != 0;
-
-    pause_l();
-    mVideoRenderer.clear();
-
-    shutdownVideoDecoder_l();
-
-    status_t err = initVideoDecoder();
-
-    if (err != OK) {
-        ALOGE("failed to reinstantiate video decoder after surface change.");
-        return err;
-    }
-
-    if (mLastVideoTimeUs >= 0) {
-        mSeeking = SEEK;
-        mSeekTimeUs = mLastVideoTimeUs;
-        modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
-    }
-
-    if (wasPlaying) {
-        play_l();
-    }
-
-    return OK;
-}
-
-void AwesomePlayer::setAudioSink(
-        const sp<MediaPlayerBase::AudioSink> &audioSink) {
-    Mutex::Autolock autoLock(mLock);
-
-    mAudioSink = audioSink;
-}
-
-status_t AwesomePlayer::setLooping(bool shouldLoop) {
-    Mutex::Autolock autoLock(mLock);
-
-    modifyFlags(LOOPING, CLEAR);
-
-    if (shouldLoop) {
-        modifyFlags(LOOPING, SET);
-    }
-
-    return OK;
-}
-
-status_t AwesomePlayer::getDuration(int64_t *durationUs) {
-    Mutex::Autolock autoLock(mMiscStateLock);
-
-    if (mDurationUs < 0) {
-        return UNKNOWN_ERROR;
-    }
-
-    *durationUs = mDurationUs;
-
-    return OK;
-}
-
-status_t AwesomePlayer::getPosition(int64_t *positionUs) {
-    if (mSeeking != NO_SEEK) {
-        *positionUs = mSeekTimeUs;
-    } else if (mVideoSource != NULL
-            && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
-        Mutex::Autolock autoLock(mMiscStateLock);
-        *positionUs = mVideoTimeUs;
-    } else if (mAudioPlayer != NULL) {
-        *positionUs = mAudioPlayer->getMediaTimeUs();
-    } else {
-        *positionUs = 0;
-    }
-    return OK;
-}
-
-status_t AwesomePlayer::seekTo(int64_t timeUs) {
-    ATRACE_CALL();
-
-    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
-        Mutex::Autolock autoLock(mLock);
-        return seekTo_l(timeUs);
-    }
-
-    return OK;
-}
-
-status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
-    if (mFlags & CACHE_UNDERRUN) {
-        modifyFlags(CACHE_UNDERRUN, CLEAR);
-        play_l();
-    }
-
-    if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
-        // Video playback completed before, there's no pending
-        // video event right now. In order for this new seek
-        // to be honored, we need to post one.
-
-        postVideoEvent_l();
-    }
-
-    mSeeking = SEEK;
-    mSeekNotificationSent = false;
-    mSeekTimeUs = timeUs;
-    modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
-
-    if (mFlags & PLAYING) {
-        notifyListener_l(MEDIA_PAUSED);
-        mMediaRenderingStartGeneration = ++mStartGeneration;
-    }
-
-    seekAudioIfNecessary_l();
-
-    if (mFlags & TEXTPLAYER_INITIALIZED) {
-        mTextDriver->seekToAsync(mSeekTimeUs);
-    }
-
-    if (!(mFlags & PLAYING)) {
-        ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
-             " immediately.");
-
-        notifyListener_l(MEDIA_SEEK_COMPLETE);
-        mSeekNotificationSent = true;
-
-        if ((mFlags & PREPARED) && mVideoSource != NULL) {
-            modifyFlags(SEEK_PREVIEW, SET);
-            postVideoEvent_l();
-        }
-    }
-
-    return OK;
-}
-
-void AwesomePlayer::seekAudioIfNecessary_l() {
-    if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
-        mAudioPlayer->seekTo(mSeekTimeUs);
-
-        mWatchForAudioSeekComplete = true;
-        mWatchForAudioEOS = true;
-
-        if (mDecryptHandle != NULL) {
-            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
-                    Playback::PAUSE, 0);
-            mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
-                    Playback::START, mSeekTimeUs / 1000);
-        }
-    }
-}
-
-void AwesomePlayer::setAudioSource(sp<IMediaSource> source) {
-    CHECK(source != NULL);
-
-    mAudioTrack = source;
-}
-
-void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<IMediaSource>& source) {
-    CHECK(source != NULL);
-
-    if (mTextDriver == NULL) {
-        mTextDriver = new TimedTextDriver(mListener, mHTTPService);
-    }
-
-    mTextDriver->addInBandTextSource(trackIndex, source);
-}
-
-status_t AwesomePlayer::initAudioDecoder() {
-    ATRACE_CALL();
-
-    sp<MetaData> meta = mAudioTrack->getFormat();
-
-    const char *mime;
-    CHECK(meta->findCString(kKeyMIMEType, &mime));
-    // Check whether there is a hardware codec for this stream
-    // This doesn't guarantee that the hardware has a free stream
-    // but it avoids us attempting to open (and re-open) an offload
-    // stream to hardware that doesn't have the necessary codec
-    audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
-    if (mAudioSink != NULL) {
-        streamType = mAudioSink->getAudioStreamType();
-    }
-
-    mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL),
-                                     isStreamingHTTP(), streamType);
-
-    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
-        ALOGV("createAudioPlayer: bypass OMX (raw)");
-        mAudioSource = mAudioTrack;
-    } else {
-        // If offloading we still create a OMX decoder as a fall-back
-        // but we don't start it
-        mOmxSource = OMXCodec::Create(
-                mClient.interface(), mAudioTrack->getFormat(),
-                false, // createEncoder
-                mAudioTrack);
-
-        if (mOffloadAudio) {
-            ALOGV("createAudioPlayer: bypass OMX (offload)");
-            mAudioSource = mAudioTrack;
-        } else {
-            mAudioSource = mOmxSource;
-        }
-    }
-
-    if (mAudioSource != NULL) {
-        int64_t durationUs;
-        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
-            Mutex::Autolock autoLock(mMiscStateLock);
-            if (mDurationUs < 0 || durationUs > mDurationUs) {
-                mDurationUs = durationUs;
-            }
-        }
-
-        status_t err = mAudioSource->start();
-
-        if (err != OK) {
-            mAudioSource.clear();
-            mOmxSource.clear();
-            return err;
-        }
-    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
-        // For legacy reasons we're simply going to ignore the absence
-        // of an audio decoder for QCELP instead of aborting playback
-        // altogether.
-        return OK;
-    }
-
-    if (mAudioSource != NULL) {
-        Mutex::Autolock autoLock(mStatsLock);
-        TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
-        const char *component;
-        if (!mAudioSource->getFormat()
-                ->findCString(kKeyDecoderComponent, &component)) {
-            component = "none";
-        }
-
-        stat->mDecoderName = component;
-    }
-
-    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
-}
-
-void AwesomePlayer::setVideoSource(sp<IMediaSource> source) {
-    CHECK(source != NULL);
-
-    mVideoTrack = source;
-}
-
-status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
-    ATRACE_CALL();
-
-    // Either the application or the DRM system can independently say
-    // that there must be a hardware-protected path to an external video sink.
-    // For now we always require a hardware-protected path to external video sink
-    // if content is DRMed, but eventually this could be optional per DRM agent.
-    // When the application wants protection, then
-    //   (USE_SURFACE_ALLOC && (mSurface != 0) &&
-    //   (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
-    // will be true, but that part is already handled by SurfaceFlinger.
-
-#ifdef DEBUG_HDCP
-    // For debugging, we allow a system property to control the protected usage.
-    // In case of uninitialized or unexpected property, we default to "DRM only".
-    bool setProtectionBit = false;
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("persist.sys.hdcp_checking", value, NULL)) {
-        if (!strcmp(value, "never")) {
-            // nop
-        } else if (!strcmp(value, "always")) {
-            setProtectionBit = true;
-        } else if (!strcmp(value, "drm-only")) {
-            if (mDecryptHandle != NULL) {
-                setProtectionBit = true;
-            }
-        // property value is empty, or unexpected value
-        } else {
-            if (mDecryptHandle != NULL) {
-                setProtectionBit = true;
-            }
-        }
-    // can' read property value
-    } else {
-        if (mDecryptHandle != NULL) {
-            setProtectionBit = true;
-        }
-    }
-    // note that usage bit is already cleared, so no need to clear it in the "else" case
-    if (setProtectionBit) {
-        flags |= OMXCodec::kEnableGrallocUsageProtected;
-    }
-#else
-    if (mDecryptHandle != NULL) {
-        flags |= OMXCodec::kEnableGrallocUsageProtected;
-    }
-#endif
-    ALOGV("initVideoDecoder flags=0x%x", flags);
-    mVideoSource = OMXCodec::Create(
-            mClient.interface(), mVideoTrack->getFormat(),
-            false, // createEncoder
-            mVideoTrack,
-            NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
-
-    if (mVideoSource != NULL) {
-        int64_t durationUs;
-        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
-            Mutex::Autolock autoLock(mMiscStateLock);
-            if (mDurationUs < 0 || durationUs > mDurationUs) {
-                mDurationUs = durationUs;
-            }
-        }
-
-        status_t err = mVideoSource->start();
-
-        if (err != OK) {
-            ALOGE("failed to start video source");
-            mVideoSource.clear();
-            return err;
-        }
-    }
-
-    if (mVideoSource != NULL) {
-        const char *componentName;
-        CHECK(mVideoSource->getFormat()
-                ->findCString(kKeyDecoderComponent, &componentName));
-
-        {
-            Mutex::Autolock autoLock(mStatsLock);
-            TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
-
-            stat->mDecoderName = componentName;
-        }
-
-        static const char *kPrefix = "OMX.Nvidia.";
-        static const char *kSuffix = ".decode";
-        static const size_t kSuffixLength = strlen(kSuffix);
-
-        size_t componentNameLength = strlen(componentName);
-
-        if (!strncmp(componentName, kPrefix, strlen(kPrefix))
-                && componentNameLength >= kSuffixLength
-                && !strcmp(&componentName[
-                    componentNameLength - kSuffixLength], kSuffix)) {
-            modifyFlags(SLOW_DECODER_HACK, SET);
-        }
-    }
-
-    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
-}
-
-void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
-    ATRACE_CALL();
-
-    if (mSeeking == SEEK_VIDEO_ONLY) {
-        mSeeking = NO_SEEK;
-        return;
-    }
-
-    if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
-        return;
-    }
-
-    // If we paused, then seeked, then resumed, it is possible that we have
-    // signaled SEEK_COMPLETE at a copmletely different media time than where
-    // we are now resuming.  Signal new position to media time provider.
-    // Cannot signal another SEEK_COMPLETE, as existing clients may not expect
-    // multiple SEEK_COMPLETE responses to a single seek() request.
-    if (mSeekNotificationSent && llabs((long long)(mSeekTimeUs - videoTimeUs)) > 10000) {
-        // notify if we are resuming more than 10ms away from desired seek time
-        notifyListener_l(MEDIA_SKIPPED);
-    }
-
-    if (mAudioPlayer != NULL) {
-        ALOGV("seeking audio to %" PRId64 " us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
-
-        // If we don't have a video time, seek audio to the originally
-        // requested seek time instead.
-
-        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
-        mWatchForAudioSeekComplete = true;
-        mWatchForAudioEOS = true;
-    } else if (!mSeekNotificationSent) {
-        // If we're playing video only, report seek complete now,
-        // otherwise audio player will notify us later.
-        notifyListener_l(MEDIA_SEEK_COMPLETE);
-        mSeekNotificationSent = true;
-    }
-
-    modifyFlags(FIRST_FRAME, SET);
-    mSeeking = NO_SEEK;
-
-    if (mDecryptHandle != NULL) {
-        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
-                Playback::PAUSE, 0);
-        mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
-                Playback::START, videoTimeUs / 1000);
-    }
-}
-
-void AwesomePlayer::onVideoEvent() {
-    ATRACE_CALL();
-    Mutex::Autolock autoLock(mLock);
-    if (!mVideoEventPending) {
-        // The event has been cancelled in reset_l() but had already
-        // been scheduled for execution at that time.
-        return;
-    }
-    mVideoEventPending = false;
-
-    if (mSeeking != NO_SEEK) {
-        if (mVideoBuffer) {
-            mVideoBuffer->release();
-            mVideoBuffer = NULL;
-        }
-
-        if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
-                && !(mFlags & SEEK_PREVIEW)) {
-            // We're going to seek the video source first, followed by
-            // the audio source.
-            // In order to avoid jumps in the DataSource offset caused by
-            // the audio codec prefetching data from the old locations
-            // while the video codec is already reading data from the new
-            // locations, we'll "pause" the audio source, causing it to
-            // stop reading input data until a subsequent seek.
-
-            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
-                mAudioPlayer->pause();
-
-                modifyFlags(AUDIO_RUNNING, CLEAR);
-            }
-            mAudioSource->pause();
-        }
-    }
-
-    if (!mVideoBuffer) {
-        MediaSource::ReadOptions options;
-        if (mSeeking != NO_SEEK) {
-            ALOGV("seeking to %" PRId64 " us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
-
-            options.setSeekTo(
-                    mSeekTimeUs,
-                    mSeeking == SEEK_VIDEO_ONLY
-                        ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
-                        : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
-        }
-        for (;;) {
-            status_t err = mVideoSource->read(&mVideoBuffer, &options);
-            options.clearSeekTo();
-
-            if (err != OK) {
-                CHECK(mVideoBuffer == NULL);
-
-                if (err == INFO_FORMAT_CHANGED) {
-                    ALOGV("VideoSource signalled format change.");
-
-                    notifyVideoSize_l();
-
-                    if (mVideoRenderer != NULL) {
-                        mVideoRendererIsPreview = false;
-                        initRenderer_l();
-                    }
-                    continue;
-                }
-
-                // So video playback is complete, but we may still have
-                // a seek request pending that needs to be applied
-                // to the audio track.
-                if (mSeeking != NO_SEEK) {
-                    ALOGV("video stream ended while seeking!");
-                }
-                finishSeekIfNecessary(-1);
-
-                if (mAudioPlayer != NULL
-                        && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
-                    startAudioPlayer_l();
-                }
-
-                modifyFlags(VIDEO_AT_EOS, SET);
-                postStreamDoneEvent_l(err);
-                return;
-            }
-
-            if (mVideoBuffer->range_length() == 0) {
-                // Some decoders, notably the PV AVC software decoder
-                // return spurious empty buffers that we just want to ignore.
-
-                mVideoBuffer->release();
-                mVideoBuffer = NULL;
-                continue;
-            }
-
-            break;
-        }
-
-        {
-            Mutex::Autolock autoLock(mStatsLock);
-            ++mStats.mNumVideoFramesDecoded;
-        }
-    }
-
-    int64_t timeUs;
-    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
-
-    mLastVideoTimeUs = timeUs;
-
-    if (mSeeking == SEEK_VIDEO_ONLY) {
-        if (mSeekTimeUs > timeUs) {
-            ALOGI("XXX mSeekTimeUs = %" PRId64 " us, timeUs = %" PRId64 " us",
-                 mSeekTimeUs, timeUs);
-        }
-    }
-
-    {
-        Mutex::Autolock autoLock(mMiscStateLock);
-        mVideoTimeUs = timeUs;
-    }
-
-    SeekType wasSeeking = mSeeking;
-    finishSeekIfNecessary(timeUs);
-
-    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
-        status_t err = startAudioPlayer_l();
-        if (err != OK) {
-            ALOGE("Starting the audio player failed w/ err %d", err);
-            return;
-        }
-    }
-
-    if ((mFlags & TEXTPLAYER_INITIALIZED)
-            && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
-        mTextDriver->start();
-        modifyFlags(TEXT_RUNNING, SET);
-    }
-
-    TimeSource *ts =
-        ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
-            ? &mSystemTimeSource : mTimeSource;
-    int64_t systemTimeUs = mSystemTimeSource.getRealTimeUs();
-    int64_t looperTimeUs = ALooper::GetNowUs();
-
-    if (mFlags & FIRST_FRAME) {
-        modifyFlags(FIRST_FRAME, CLEAR);
-        mSinceLastDropped = 0;
-        mClockEstimator->reset();
-        mTimeSourceDeltaUs = estimateRealTimeUs(ts, systemTimeUs) - timeUs;
-    }
-
-    int64_t realTimeUs, mediaTimeUs;
-    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
-        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
-        ALOGV("updating TSdelta (%" PRId64 " => %" PRId64 " change %" PRId64 ")",
-              mTimeSourceDeltaUs, realTimeUs - mediaTimeUs,
-              mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs));
-        ATRACE_INT("TS delta change (ms)", (mTimeSourceDeltaUs - (realTimeUs - mediaTimeUs)) / 1E3);
-        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
-    }
-
-    if (wasSeeking == SEEK_VIDEO_ONLY) {
-        int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs;
-
-        int64_t latenessUs = nowUs - timeUs;
-
-        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
-
-        if (latenessUs > 0) {
-            ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
-        }
-    }
-
-    int64_t latenessUs = 0;
-    if (wasSeeking == NO_SEEK) {
-        // Let's display the first frame after seeking right away.
-
-        int64_t nowUs = estimateRealTimeUs(ts, systemTimeUs) - mTimeSourceDeltaUs;
-
-        latenessUs = nowUs - timeUs;
-
-        ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
-
-        if (latenessUs > 500000ll
-                && mAudioPlayer != NULL
-                && mAudioPlayer->getMediaTimeMapping(
-                    &realTimeUs, &mediaTimeUs)) {
-            if (mWVMExtractor == NULL) {
-                ALOGI("we're much too late (%.2f secs), video skipping ahead",
-                     latenessUs / 1E6);
-
-                mVideoBuffer->release();
-                mVideoBuffer = NULL;
-
-                mSeeking = SEEK_VIDEO_ONLY;
-                mSeekTimeUs = mediaTimeUs;
-
-                postVideoEvent_l();
-                return;
-            } else {
-                // The widevine extractor doesn't deal well with seeking
-                // audio and video independently. We'll just have to wait
-                // until the decoder catches up, which won't be long at all.
-                ALOGI("we're very late (%.2f secs)", latenessUs / 1E6);
-            }
-        }
-
-        if (latenessUs > 40000) {
-            // We're more than 40ms late.
-            ALOGV("we're late by %" PRId64 " us (%.2f secs)",
-                 latenessUs, latenessUs / 1E6);
-
-            if (!(mFlags & SLOW_DECODER_HACK)
-                    || mSinceLastDropped > FRAME_DROP_FREQ)
-            {
-                ALOGV("we're late by %" PRId64 " us (%.2f secs) dropping "
-                     "one after %d frames",
-                     latenessUs, latenessUs / 1E6, mSinceLastDropped);
-
-                mSinceLastDropped = 0;
-                mVideoBuffer->release();
-                mVideoBuffer = NULL;
-
-                {
-                    Mutex::Autolock autoLock(mStatsLock);
-                    ++mStats.mNumVideoFramesDropped;
-                }
-
-                postVideoEvent_l(0);
-                return;
-            }
-        }
-
-        if (latenessUs < -30000) {
-            // We're more than 30ms early, schedule at most 20 ms before time due
-            postVideoEvent_l(latenessUs < -60000 ? 30000 : -latenessUs - 20000);
-            return;
-        }
-    }
-
-    if ((mNativeWindow != NULL)
-            && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
-        mVideoRendererIsPreview = false;
-
-        initRenderer_l();
-    }
-
-    if (mVideoRenderer != NULL) {
-        mSinceLastDropped++;
-        mVideoBuffer->meta_data()->setInt64(kKeyTime, looperTimeUs - latenessUs);
-
-        mVideoRenderer->render(mVideoBuffer);
-        if (!mVideoRenderingStarted) {
-            mVideoRenderingStarted = true;
-            notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START);
-        }
-
-        if (mFlags & PLAYING) {
-            notifyIfMediaStarted_l();
-        }
-    }
-
-    mVideoBuffer->release();
-    mVideoBuffer = NULL;
-
-    if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
-        modifyFlags(SEEK_PREVIEW, CLEAR);
-        return;
-    }
-
-    /* get next frame time */
-    if (wasSeeking == NO_SEEK) {
-        MediaSource::ReadOptions options;
-        for (;;) {
-            status_t err = mVideoSource->read(&mVideoBuffer, &options);
-            if (err != OK) {
-                // deal with any errors next time
-                CHECK(mVideoBuffer == NULL);
-                postVideoEvent_l(0);
-                return;
-            }
-
-            if (mVideoBuffer->range_length() != 0) {
-                break;
-            }
-
-            // Some decoders, notably the PV AVC software decoder
-            // return spurious empty buffers that we just want to ignore.
-
-            mVideoBuffer->release();
-            mVideoBuffer = NULL;
-        }
-
-        {
-            Mutex::Autolock autoLock(mStatsLock);
-            ++mStats.mNumVideoFramesDecoded;
-        }
-
-        int64_t nextTimeUs;
-        CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &nextTimeUs));
-        systemTimeUs = mSystemTimeSource.getRealTimeUs();
-        int64_t delayUs = nextTimeUs - estimateRealTimeUs(ts, systemTimeUs) + mTimeSourceDeltaUs;
-        ATRACE_INT("Frame delta (ms)", (nextTimeUs - timeUs) / 1E3);
-        ALOGV("next frame in %" PRId64, delayUs);
-        // try to schedule 30ms before time due
-        postVideoEvent_l(delayUs > 60000 ? 30000 : (delayUs < 30000 ? 0 : delayUs - 30000));
-        return;
-    }
-
-    postVideoEvent_l();
-}
-
-int64_t AwesomePlayer::estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs) {
-    if (ts == &mSystemTimeSource) {
-        return systemTimeUs;
-    } else {
-        return (int64_t)mClockEstimator->estimate(systemTimeUs, ts->getRealTimeUs());
-    }
-}
-
-void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
-    ATRACE_CALL();
-
-    if (mVideoEventPending) {
-        return;
-    }
-
-    mVideoEventPending = true;
-    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
-}
-
-void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
-    if (mStreamDoneEventPending) {
-        return;
-    }
-    mStreamDoneEventPending = true;
-
-    mStreamDoneStatus = status;
-    mQueue.postEvent(mStreamDoneEvent);
-}
-
-void AwesomePlayer::postBufferingEvent_l() {
-    if (mBufferingEventPending) {
-        return;
-    }
-    mBufferingEventPending = true;
-    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
-}
-
-void AwesomePlayer::postVideoLagEvent_l() {
-    if (mVideoLagEventPending) {
-        return;
-    }
-    mVideoLagEventPending = true;
-    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
-}
-
-void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
-    Mutex::Autolock autoLock(mAudioLock);
-    if (mAudioStatusEventPending) {
-        return;
-    }
-    mAudioStatusEventPending = true;
-    // Do not honor delay when looping in order to limit audio gap
-    if (mFlags & (LOOPING | AUTO_LOOPING)) {
-        delayUs = 0;
-    }
-    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
-}
-
-void AwesomePlayer::postAudioTearDownEvent(int64_t delayUs) {
-    Mutex::Autolock autoLock(mAudioLock);
-    if (mAudioTearDownEventPending) {
-        return;
-    }
-    mAudioTearDownEventPending = true;
-    mQueue.postEventWithDelay(mAudioTearDownEvent, delayUs);
-}
-
-void AwesomePlayer::onCheckAudioStatus() {
-    {
-        Mutex::Autolock autoLock(mAudioLock);
-        if (!mAudioStatusEventPending) {
-            // Event was dispatched and while we were blocking on the mutex,
-            // has already been cancelled.
-            return;
-        }
-
-        mAudioStatusEventPending = false;
-    }
-
-    Mutex::Autolock autoLock(mLock);
-
-    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
-        mWatchForAudioSeekComplete = false;
-
-        if (!mSeekNotificationSent) {
-            notifyListener_l(MEDIA_SEEK_COMPLETE);
-            mSeekNotificationSent = true;
-        }
-
-        if (mVideoSource == NULL) {
-            // For video the mSeeking flag is always reset in finishSeekIfNecessary
-            mSeeking = NO_SEEK;
-        }
-
-        notifyIfMediaStarted_l();
-    }
-
-    status_t finalStatus;
-    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
-        mWatchForAudioEOS = false;
-        modifyFlags(AUDIO_AT_EOS, SET);
-        modifyFlags(FIRST_FRAME, SET);
-        postStreamDoneEvent_l(finalStatus);
-    }
-}
-
-status_t AwesomePlayer::prepare() {
-    ATRACE_CALL();
-    Mutex::Autolock autoLock(mLock);
-    return prepare_l();
-}
-
-status_t AwesomePlayer::prepare_l() {
-    if (mFlags & PREPARED) {
-        return OK;
-    }
-
-    if (mFlags & PREPARING) {
-        return UNKNOWN_ERROR;
-    }
-
-    mIsAsyncPrepare = false;
-    status_t err = prepareAsync_l();
-
-    if (err != OK) {
-        return err;
-    }
-
-    while (mFlags & PREPARING) {
-        mPreparedCondition.wait(mLock);
-    }
-
-    return mPrepareResult;
-}
-
-status_t AwesomePlayer::prepareAsync() {
-    ATRACE_CALL();
-    Mutex::Autolock autoLock(mLock);
-
-    if (mFlags & PREPARING) {
-        return UNKNOWN_ERROR;  // async prepare already pending
-    }
-
-    mIsAsyncPrepare = true;
-    return prepareAsync_l();
-}
-
-status_t AwesomePlayer::prepareAsync_l() {
-    if (mFlags & PREPARING) {
-        return UNKNOWN_ERROR;  // async prepare already pending
-    }
-
-    if (!mQueueStarted) {
-        mQueue.start();
-        mQueueStarted = true;
-    }
-
-    modifyFlags(PREPARING, SET);
-    mAsyncPrepareEvent = new AwesomeEvent(
-            this, &AwesomePlayer::onPrepareAsyncEvent);
-
-    mQueue.postEvent(mAsyncPrepareEvent);
-
-    return OK;
-}
-
-status_t AwesomePlayer::finishSetDataSource_l() {
-    ATRACE_CALL();
-    sp<DataSource> dataSource;
-
-    bool isWidevineStreaming = false;
-    if (!strncasecmp("widevine://", mUri.string(), 11)) {
-        isWidevineStreaming = true;
-
-        String8 newURI = String8("http://");
-        newURI.append(mUri.string() + 11);
-
-        mUri = newURI;
-    }
-
-    AString sniffedMIME;
-
-    if (!strncasecmp("http://", mUri.string(), 7)
-            || !strncasecmp("https://", mUri.string(), 8)
-            || isWidevineStreaming) {
-        if (mHTTPService == NULL) {
-            ALOGE("Attempt to play media from http URI without HTTP service.");
-            return UNKNOWN_ERROR;
-        }
-
-        sp<IMediaHTTPConnection> conn = mHTTPService->makeHTTPConnection();
-        mConnectingDataSource = new MediaHTTP(conn);
-
-        String8 cacheConfig;
-        bool disconnectAtHighwatermark;
-        NuCachedSource2::RemoveCacheSpecificHeaders(
-                &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
-
-        mLock.unlock();
-        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
-        // force connection at this point, to avoid a race condition between getMIMEType and the
-        // caching datasource constructed below, which could result in multiple requests to the
-        // server, and/or failed connections.
-        String8 contentType = mConnectingDataSource->getMIMEType();
-        mLock.lock();
-
-        if (err != OK) {
-            mConnectingDataSource.clear();
-
-            ALOGI("mConnectingDataSource->connect() returned %d", err);
-            return err;
-        }
-
-        if (!isWidevineStreaming) {
-            // The widevine extractor does its own caching.
-
-#if 0
-            mCachedSource = NuCachedSource2::Create(
-                    new ThrottledSource(
-                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
-#else
-            mCachedSource = NuCachedSource2::Create(
-                    mConnectingDataSource,
-                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
-                    disconnectAtHighwatermark);
-#endif
-
-            dataSource = mCachedSource;
-        } else {
-            dataSource = mConnectingDataSource;
-        }
-
-        mConnectingDataSource.clear();
-
-        if (strncasecmp(contentType.string(), "audio/", 6)) {
-            // We're not doing this for streams that appear to be audio-only
-            // streams to ensure that even low bandwidth streams start
-            // playing back fairly instantly.
-
-            // We're going to prefill the cache before trying to instantiate
-            // the extractor below, as the latter is an operation that otherwise
-            // could block on the datasource for a significant amount of time.
-            // During that time we'd be unable to abort the preparation phase
-            // without this prefill.
-            if (mCachedSource != NULL) {
-                // We're going to prefill the cache before trying to instantiate
-                // the extractor below, as the latter is an operation that otherwise
-                // could block on the datasource for a significant amount of time.
-                // During that time we'd be unable to abort the preparation phase
-                // without this prefill.
-
-                mLock.unlock();
-
-                // Initially make sure we have at least 192 KB for the sniff
-                // to complete without blocking.
-                static const size_t kMinBytesForSniffing = 192 * 1024;
-
-                off64_t metaDataSize = -1ll;
-                for (;;) {
-                    status_t finalStatus;
-                    size_t cachedDataRemaining =
-                        mCachedSource->approxDataRemaining(&finalStatus);
-
-                    if (finalStatus != OK
-                            || (metaDataSize >= 0
-                                && (off64_t)cachedDataRemaining >= metaDataSize)
-                            || (mFlags & PREPARE_CANCELLED)) {
-                        break;
-                    }
-
-                    ALOGV("now cached %zu bytes of data", cachedDataRemaining);
-
-                    if (metaDataSize < 0
-                            && cachedDataRemaining >= kMinBytesForSniffing) {
-                        String8 tmp;
-                        float confidence;
-                        sp<AMessage> meta;
-                        if (!dataSource->sniff(&tmp, &confidence, &meta)) {
-                            mLock.lock();
-                            return UNKNOWN_ERROR;
-                        }
-
-                        // We successfully identified the file's extractor to
-                        // be, remember this mime type so we don't have to
-                        // sniff it again when we call MediaExtractor::Create()
-                        // below.
-                        sniffedMIME = tmp.string();
-
-                        if (meta == NULL
-                                || !meta->findInt64("meta-data-size",
-                                     reinterpret_cast<int64_t*>(&metaDataSize))) {
-                            metaDataSize = kHighWaterMarkBytes;
-                        }
-
-                        CHECK_GE(metaDataSize, 0ll);
-                        ALOGV("metaDataSize = %lld bytes", (long long)metaDataSize);
-                    }
-
-                    usleep(200000);
-                }
-
-                mLock.lock();
-            }
-
-            if (mFlags & PREPARE_CANCELLED) {
-                ALOGI("Prepare cancelled while waiting for initial cache fill.");
-                return UNKNOWN_ERROR;
-            }
-        }
-    } else {
-        dataSource = DataSource::CreateFromURI(
-                mHTTPService, mUri.string(), &mUriHeaders);
-    }
-
-    if (dataSource == NULL) {
-        return UNKNOWN_ERROR;
-    }
-
-    sp<IMediaExtractor> extractor;
-
-    if (isWidevineStreaming) {
-        String8 mimeType;
-        float confidence;
-        sp<AMessage> dummy;
-        bool success;
-
-        // SniffWVM is potentially blocking since it may require network access.
-        // Do not call it with mLock held.
-        mLock.unlock();
-        success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
-        mLock.lock();
-
-        if (!success
-                || strcasecmp(
-                    mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
-            return ERROR_UNSUPPORTED;
-        }
-
-        mWVMExtractor = new WVMExtractor(dataSource);
-        mWVMExtractor->setAdaptiveStreamingMode(true);
-        if (mUIDValid)
-            mWVMExtractor->setUID(mUID);
-        extractor = mWVMExtractor;
-    } else {
-        extractor = MediaExtractor::Create(
-                dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
-
-        if (extractor == NULL) {
-            return UNKNOWN_ERROR;
-        }
-    }
-
-    if (extractor->getDrmFlag()) {
-        checkDrmStatus(dataSource);
-    }
-
-    status_t err = setDataSource_l(extractor);
-
-    if (err != OK) {
-        mWVMExtractor.clear();
-
-        return err;
-    }
-
-    return OK;
-}
-
-void AwesomePlayer::abortPrepare(status_t err) {
-    CHECK(err != OK);
-
-    if (mIsAsyncPrepare) {
-        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
-    }
-
-    mPrepareResult = err;
-    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
-    mAsyncPrepareEvent = NULL;
-    mPreparedCondition.broadcast();
-    mAudioTearDown = false;
-}
-
-// static
-bool AwesomePlayer::ContinuePreparation(void *cookie) {
-    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
-
-    return (me->mFlags & PREPARE_CANCELLED) == 0;
-}
-
-void AwesomePlayer::onPrepareAsyncEvent() {
-    Mutex::Autolock autoLock(mLock);
-    beginPrepareAsync_l();
-}
-
-void AwesomePlayer::beginPrepareAsync_l() {
-    if (mFlags & PREPARE_CANCELLED) {
-        ALOGI("prepare was cancelled before doing anything");
-        abortPrepare(UNKNOWN_ERROR);
-        return;
-    }
-
-    if (mUri.size() > 0) {
-        status_t err = finishSetDataSource_l();
-
-        if (err != OK) {
-            abortPrepare(err);
-            return;
-        }
-    }
-
-    if (mVideoTrack != NULL && mVideoSource == NULL) {
-        status_t err = initVideoDecoder();
-
-        if (err != OK) {
-            abortPrepare(err);
-            return;
-        }
-    }
-
-    if (mAudioTrack != NULL && mAudioSource == NULL) {
-        status_t err = initAudioDecoder();
-
-        if (err != OK) {
-            abortPrepare(err);
-            return;
-        }
-    }
-
-    modifyFlags(PREPARING_CONNECTED, SET);
-
-    if (isStreamingHTTP()) {
-        postBufferingEvent_l();
-    } else {
-        finishAsyncPrepare_l();
-    }
-}
-
-void AwesomePlayer::finishAsyncPrepare_l() {
-    if (mIsAsyncPrepare) {
-        if (mVideoSource == NULL) {
-            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
-        } else {
-            notifyVideoSize_l();
-        }
-
-        notifyListener_l(MEDIA_PREPARED);
-    }
-
-    mPrepareResult = OK;
-    modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
-    modifyFlags(PREPARED, SET);
-    mAsyncPrepareEvent = NULL;
-    mPreparedCondition.broadcast();
-
-    if (mAudioTearDown) {
-        if (mPrepareResult == OK) {
-            if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
-                seekTo_l(mAudioTearDownPosition);
-            }
-
-            if (mAudioTearDownWasPlaying) {
-                modifyFlags(CACHE_UNDERRUN, CLEAR);
-                play_l();
-            }
-        }
-        mAudioTearDown = false;
-    }
-}
-
-uint32_t AwesomePlayer::flags() const {
-    return mExtractorFlags;
-}
-
-void AwesomePlayer::postAudioEOS(int64_t delayUs) {
-    postCheckAudioStatusEvent(delayUs);
-}
-
-void AwesomePlayer::postAudioSeekComplete() {
-    postCheckAudioStatusEvent(0);
-}
-
-void AwesomePlayer::postAudioTearDown() {
-    postAudioTearDownEvent(0);
-}
-
-status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
-    switch (key) {
-        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
-        {
-            return setCacheStatCollectFreq(request);
-        }
-        default:
-        {
-            return ERROR_UNSUPPORTED;
-        }
-    }
-}
-
-status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
-    if (mCachedSource != NULL) {
-        int32_t freqMs = request.readInt32();
-        ALOGD("Request to keep cache stats in the past %d ms",
-            freqMs);
-        return mCachedSource->setCacheStatCollectFreq(freqMs);
-    }
-    return ERROR_UNSUPPORTED;
-}
-
-status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
-    switch (key) {
-    case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
-        {
-            int32_t channelCount;
-            if (mAudioTrack == 0 ||
-                    !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
-                channelCount = 0;
-            }
-            reply->writeInt32(channelCount);
-        }
-        return OK;
-    default:
-        {
-            return ERROR_UNSUPPORTED;
-        }
-    }
-}
-
-status_t AwesomePlayer::setPlaybackSettings(const AudioPlaybackRate &rate) {
-    Mutex::Autolock autoLock(mLock);
-    // cursory sanity check for non-audio and paused cases
-    if ((rate.mSpeed != 0.f && rate.mSpeed < AUDIO_TIMESTRETCH_SPEED_MIN)
-        || rate.mSpeed > AUDIO_TIMESTRETCH_SPEED_MAX
-        || rate.mPitch < AUDIO_TIMESTRETCH_SPEED_MIN
-        || rate.mPitch > AUDIO_TIMESTRETCH_SPEED_MAX) {
-        return BAD_VALUE;
-    }
-
-    status_t err = OK;
-    if (rate.mSpeed == 0.f) {
-        if (mFlags & PLAYING) {
-            modifyFlags(CACHE_UNDERRUN, CLEAR); // same as pause
-            err = pause_l();
-        }
-        if (err == OK) {
-            // save settings (using old speed) in case player is resumed
-            AudioPlaybackRate newRate = rate;
-            newRate.mSpeed = mPlaybackSettings.mSpeed;
-            mPlaybackSettings = newRate;
-        }
-        return err;
-    }
-    if (mAudioPlayer != NULL) {
-        err = mAudioPlayer->setPlaybackRate(rate);
-    }
-    if (err == OK) {
-        mPlaybackSettings = rate;
-        if (!(mFlags & PLAYING)) {
-            play_l();
-        }
-    }
-    return err;
-}
-
-status_t AwesomePlayer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
-    if (mAudioPlayer != NULL) {
-        status_t err = mAudioPlayer->getPlaybackRate(rate);
-        if (err == OK) {
-            mPlaybackSettings = *rate;
-            Mutex::Autolock autoLock(mLock);
-            if (!(mFlags & PLAYING)) {
-                rate->mSpeed = 0.f;
-            }
-        }
-        return err;
-    }
-    *rate = mPlaybackSettings;
-    return OK;
-}
-
-status_t AwesomePlayer::getTrackInfo(Parcel *reply) const {
-    Mutex::Autolock autoLock(mLock);
-    size_t trackCount = mExtractor->countTracks();
-    if (mTextDriver != NULL) {
-        trackCount += mTextDriver->countExternalTracks();
-    }
-
-    reply->writeInt32(trackCount);
-    for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
-        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
-
-        const char *_mime;
-        CHECK(meta->findCString(kKeyMIMEType, &_mime));
-
-        String8 mime = String8(_mime);
-
-        reply->writeInt32(2); // 2 fields
-
-        if (!strncasecmp(mime.string(), "video/", 6)) {
-            reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
-        } else if (!strncasecmp(mime.string(), "audio/", 6)) {
-            reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
-        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
-            reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
-        } else {
-            reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
-        }
-        reply->writeString16(String16(mime));
-
-        const char *lang;
-        if (!meta->findCString(kKeyMediaLanguage, &lang)) {
-            lang = "und";
-        }
-        reply->writeString16(String16(lang));
-    }
-
-    if (mTextDriver != NULL) {
-        mTextDriver->getExternalTrackInfo(reply);
-    }
-    return OK;
-}
-
-status_t AwesomePlayer::selectAudioTrack_l(
-        const sp<IMediaSource>& source, size_t trackIndex) {
-
-    ALOGI("selectAudioTrack_l: trackIndex=%zu, mFlags=0x%x", trackIndex, mFlags);
-
-    {
-        Mutex::Autolock autoLock(mStatsLock);
-        if ((ssize_t)trackIndex == mActiveAudioTrackIndex) {
-            ALOGI("Track %zu is active. Does nothing.", trackIndex);
-            return OK;
-        }
-        //mStats.mFlags = mFlags;
-    }
-
-    if (mSeeking != NO_SEEK) {
-        ALOGE("Selecting a track while seeking is not supported");
-        return ERROR_UNSUPPORTED;
-    }
-
-    if ((mFlags & PREPARED) == 0) {
-        ALOGE("Data source has not finished preparation");
-        return ERROR_UNSUPPORTED;
-    }
-
-    CHECK(source != NULL);
-    bool wasPlaying = (mFlags & PLAYING) != 0;
-
-    pause_l();
-
-    int64_t curTimeUs;
-    CHECK_EQ(getPosition(&curTimeUs), (status_t)OK);
-
-    if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
-            && mAudioSource != NULL) {
-        // If we had an audio player, it would have effectively
-        // taken possession of the audio source and stopped it when
-        // _it_ is stopped. Otherwise this is still our responsibility.
-        mAudioSource->stop();
-    }
-    mAudioSource.clear();
-    mOmxSource.clear();
-
-    mTimeSource = NULL;
-
-    delete mAudioPlayer;
-    mAudioPlayer = NULL;
-
-    modifyFlags(AUDIOPLAYER_STARTED, CLEAR);
-
-    setAudioSource(source);
-
-    modifyFlags(AUDIO_AT_EOS, CLEAR);
-    modifyFlags(AT_EOS, CLEAR);
-
-    status_t err;
-    if ((err = initAudioDecoder()) != OK) {
-        ALOGE("Failed to init audio decoder: 0x%x", err);
-        return err;
-    }
-
-    mSeekNotificationSent = true;
-    seekTo_l(curTimeUs);
-
-    if (wasPlaying) {
-        play_l();
-    }
-
-    mActiveAudioTrackIndex = trackIndex;
-
-    return OK;
-}
-
-status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
-    ATRACE_CALL();
-    ALOGV("selectTrack: trackIndex = %zu and select=%d", trackIndex, select);
-    Mutex::Autolock autoLock(mLock);
-    size_t trackCount = mExtractor->countTracks();
-    if (mTextDriver != NULL) {
-        trackCount += mTextDriver->countExternalTracks();
-    }
-    if (trackIndex >= trackCount) {
-        ALOGE("Track index (%zu) is out of range [0, %zu)", trackIndex, trackCount);
-        return ERROR_OUT_OF_RANGE;
-    }
-
-    bool isAudioTrack = false;
-    if (trackIndex < mExtractor->countTracks()) {
-        sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
-        const char *mime;
-        CHECK(meta->findCString(kKeyMIMEType, &mime));
-        isAudioTrack = !strncasecmp(mime, "audio/", 6);
-
-        if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) {
-            ALOGE("Track %zu is not either audio or timed text", trackIndex);
-            return ERROR_UNSUPPORTED;
-        }
-    }
-
-    if (isAudioTrack) {
-        if (!select) {
-            ALOGE("Deselect an audio track (%zu) is not supported", trackIndex);
-            return ERROR_UNSUPPORTED;
-        }
-        return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex);
-    }
-
-    // Timed text track handling
-    if (mTextDriver == NULL) {
-        return INVALID_OPERATION;
-    }
-
-    status_t err = OK;
-    if (select) {
-        err = mTextDriver->selectTrack(trackIndex);
-        if (err == OK) {
-            modifyFlags(TEXTPLAYER_INITIALIZED, SET);
-            if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
-                mTextDriver->start();
-                modifyFlags(TEXT_RUNNING, SET);
-            }
-            mSelectedTimedTextTrack = trackIndex;
-        }
-    } else {
-        err = mTextDriver->unselectTrack(trackIndex);
-        if (err == OK) {
-            modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
-            modifyFlags(TEXT_RUNNING, CLEAR);
-            mSelectedTimedTextTrack = -1;
-        }
-    }
-    return err;
-}
-
-size_t AwesomePlayer::countTracks() const {
-    return mExtractor->countTracks() + mTextDriver->countExternalTracks();
-}
-
-status_t AwesomePlayer::setVideoScalingMode(int32_t mode) {
-    Mutex::Autolock lock(mLock);
-    return setVideoScalingMode_l(mode);
-}
-
-status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) {
-    mVideoScalingMode = mode;
-    if (mNativeWindow != NULL) {
-        status_t err = native_window_set_scaling_mode(
-                mNativeWindow.get(), mVideoScalingMode);
-        if (err != OK) {
-            ALOGW("Failed to set scaling mode: %d", err);
-        }
-        return err;
-    }
-    return OK;
-}
-
-status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
-    ATRACE_CALL();
-    if (NULL == reply) {
-        return android::BAD_VALUE;
-    }
-    int32_t methodId;
-    status_t ret = request.readInt32(&methodId);
-    if (ret != android::OK) {
-        return ret;
-    }
-    switch(methodId) {
-        case INVOKE_ID_SET_VIDEO_SCALING_MODE:
-        {
-            int mode = request.readInt32();
-            return setVideoScalingMode(mode);
-        }
-
-        case INVOKE_ID_GET_TRACK_INFO:
-        {
-            return getTrackInfo(reply);
-        }
-        case INVOKE_ID_ADD_EXTERNAL_SOURCE:
-        {
-            Mutex::Autolock autoLock(mLock);
-            if (mTextDriver == NULL) {
-                mTextDriver = new TimedTextDriver(mListener, mHTTPService);
-            }
-            // String values written in Parcel are UTF-16 values.
-            String8 uri(request.readString16());
-            String8 mimeType(request.readString16());
-            size_t nTracks = countTracks();
-            return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType);
-        }
-        case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
-        {
-            Mutex::Autolock autoLock(mLock);
-            if (mTextDriver == NULL) {
-                mTextDriver = new TimedTextDriver(mListener, mHTTPService);
-            }
-            int fd         = request.readFileDescriptor();
-            off64_t offset = request.readInt64();
-            off64_t length  = request.readInt64();
-            String8 mimeType(request.readString16());
-            size_t nTracks = countTracks();
-            return mTextDriver->addOutOfBandTextSource(
-                    nTracks, fd, offset, length, mimeType);
-        }
-        case INVOKE_ID_SELECT_TRACK:
-        {
-            int trackIndex = request.readInt32();
-            return selectTrack(trackIndex, true /* select */);
-        }
-        case INVOKE_ID_UNSELECT_TRACK:
-        {
-            int trackIndex = request.readInt32();
-            return selectTrack(trackIndex, false /* select */);
-        }
-        case INVOKE_ID_GET_SELECTED_TRACK:
-        {
-            int trackType = request.readInt32();
-            if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
-                reply->writeInt32(mSelectedTimedTextTrack);
-                return mSelectedTimedTextTrack;
-            }
-
-        }
-        default:
-        {
-            return ERROR_UNSUPPORTED;
-        }
-    }
-    // It will not reach here.
-    return OK;
-}
-
-bool AwesomePlayer::isStreamingHTTP() const {
-    return mCachedSource != NULL || mWVMExtractor != NULL;
-}
-
-status_t AwesomePlayer::dump(
-        int fd, const Vector<String16> & /* args */) const {
-    Mutex::Autolock autoLock(mStatsLock);
-
-    FILE *out = fdopen(dup(fd), "w");
-
-    fprintf(out, " AwesomePlayer\n");
-    if (mStats.mFd < 0) {
-        fprintf(out, "  URI(%s)", uriDebugString(mUri, mFlags & INCOGNITO).c_str());
-    } else {
-        fprintf(out, "  fd(%d)", mStats.mFd);
-    }
-
-    fprintf(out, ", flags(0x%08x)", mStats.mFlags);
-
-    if (mStats.mBitrate >= 0) {
-        fprintf(out, ", bitrate(%" PRId64 " bps)", mStats.mBitrate);
-    }
-
-    fprintf(out, "\n");
-
-    for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
-        const TrackStat &stat = mStats.mTracks.itemAt(i);
-
-        fprintf(out, "  Track %zu\n", i + 1);
-        fprintf(out, "   MIME(%s)", stat.mMIME.string());
-
-        if (!stat.mDecoderName.isEmpty()) {
-            fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
-        }
-
-        fprintf(out, "\n");
-
-        if ((ssize_t)i == mStats.mVideoTrackIndex) {
-            fprintf(out,
-                    "   videoDimensions(%d x %d), "
-                    "numVideoFramesDecoded(%" PRId64 "), "
-                    "numVideoFramesDropped(%" PRId64 ")\n",
-                    mStats.mVideoWidth,
-                    mStats.mVideoHeight,
-                    mStats.mNumVideoFramesDecoded,
-                    mStats.mNumVideoFramesDropped);
-        }
-    }
-
-    fclose(out);
-    out = NULL;
-
-    return OK;
-}
-
-void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
-    switch (mode) {
-        case SET:
-            mFlags |= value;
-            break;
-        case CLEAR:
-            if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) {
-                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
-            }
-            mFlags &= ~value;
-            break;
-        case ASSIGN:
-            mFlags = value;
-            break;
-        default:
-            TRESPASS();
-    }
-
-    {
-        Mutex::Autolock autoLock(mStatsLock);
-        mStats.mFlags = mFlags;
-    }
-}
-
-void AwesomePlayer::onAudioTearDownEvent() {
-
-    Mutex::Autolock autoLock(mLock);
-    if (!mAudioTearDownEventPending) {
-        return;
-    }
-    mAudioTearDownEventPending = false;
-
-    ALOGV("onAudioTearDownEvent");
-
-    // stream info is cleared by reset_l() so copy what we need
-    mAudioTearDownWasPlaying = (mFlags & PLAYING);
-    KeyedVector<String8, String8> uriHeaders(mUriHeaders);
-    sp<DataSource> fileSource(mFileSource);
-
-    mStatsLock.lock();
-    String8 uri(mStats.mURI);
-    mStatsLock.unlock();
-
-    // get current position so we can start recreated stream from here
-    getPosition(&mAudioTearDownPosition);
-
-    sp<IMediaHTTPService> savedHTTPService = mHTTPService;
-
-    bool wasLooping = mFlags & LOOPING;
-    // Reset and recreate
-    reset_l();
-
-    status_t err;
-
-    if (fileSource != NULL) {
-        mFileSource = fileSource;
-        err = setDataSource_l(fileSource);
-    } else {
-        err = setDataSource_l(savedHTTPService, uri, &uriHeaders);
-    }
-
-    mFlags |= PREPARING;
-    if ( err != OK ) {
-        // This will force beingPrepareAsync_l() to notify
-        // a MEDIA_ERROR to the client and abort the prepare
-        mFlags |= PREPARE_CANCELLED;
-    }
-    if (wasLooping) {
-        mFlags |= LOOPING;
-    }
-
-    mAudioTearDown = true;
-    mIsAsyncPrepare = true;
-
-    // Call prepare for the host decoding
-    beginPrepareAsync_l();
-}
-
-}  // namespace android
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index a148d55..3a3a538 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -43,15 +43,19 @@
 const int kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
 const int kDefaultSwVideoEncoderDataSpace = HAL_DATASPACE_BT709;
 
+const int kStopTimeoutUs = 300000; // allow 1 sec for shutting down encoder
+
 struct MediaCodecSource::Puller : public AHandler {
     Puller(const sp<MediaSource> &source);
 
     status_t start(const sp<MetaData> &meta, const sp<AMessage> &notify);
     void stop();
-
+    void stopSource();
     void pause();
     void resume();
 
+    bool readBuffer(MediaBuffer **buffer);
+
 protected:
     virtual void onMessageReceived(const sp<AMessage> &msg);
     virtual ~Puller();
@@ -61,17 +65,31 @@
         kWhatStart = 'msta',
         kWhatStop,
         kWhatPull,
-        kWhatPause,
-        kWhatResume,
     };
 
     sp<MediaSource> mSource;
     sp<AMessage> mNotify;
     sp<ALooper> mLooper;
-    int32_t mPullGeneration;
     bool mIsAudio;
-    bool mPaused;
-    bool mReachedEOS;
+
+    struct Queue {
+        Queue()
+            : mReadPendingSince(0),
+              mPaused(false),
+              mPulling(false) { }
+        int64_t mReadPendingSince;
+        bool mPaused;
+        bool mPulling;
+        Vector<MediaBuffer *> mReadBuffers;
+
+        void flush();
+        // if queue is empty, return false and set *|buffer| to NULL . Otherwise, pop
+        // buffer from front of the queue, place it into *|buffer| and return true. 
+        bool readBuffer(MediaBuffer **buffer);
+        // add a buffer to the back of the queue 
+        void pushBuffer(MediaBuffer *mbuf);
+    };
+    Mutexed<Queue> mQueue;
 
     status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
     void schedulePull();
@@ -83,10 +101,8 @@
 MediaCodecSource::Puller::Puller(const sp<MediaSource> &source)
     : mSource(source),
       mLooper(new ALooper()),
-      mPullGeneration(0),
-      mIsAudio(false),
-      mPaused(false),
-      mReachedEOS(false) {
+      mIsAudio(false)
+{
     sp<MetaData> meta = source->getFormat();
     const char *mime;
     CHECK(meta->findCString(kKeyMIMEType, &mime));
@@ -101,6 +117,33 @@
     mLooper->stop();
 }
 
+void MediaCodecSource::Puller::Queue::pushBuffer(MediaBuffer *mbuf) {
+    mReadBuffers.push_back(mbuf);
+}
+
+bool MediaCodecSource::Puller::Queue::readBuffer(MediaBuffer **mbuf) {
+    if (mReadBuffers.empty()) {
+        *mbuf = NULL;
+        return false;
+    }
+    *mbuf = *mReadBuffers.begin();
+    mReadBuffers.erase(mReadBuffers.begin());
+    return true;
+}
+
+void MediaCodecSource::Puller::Queue::flush() {
+    MediaBuffer *mbuf;
+    while (readBuffer(&mbuf)) {
+        // there are no null buffers in the queue
+        mbuf->release();
+    }
+}
+
+bool MediaCodecSource::Puller::readBuffer(MediaBuffer **mbuf) {
+    Mutexed<Queue>::Locked queue(mQueue);
+    return queue->readBuffer(mbuf);
+}
+
 status_t MediaCodecSource::Puller::postSynchronouslyAndReturnError(
         const sp<AMessage> &msg) {
     sp<AMessage> response;
@@ -117,8 +160,7 @@
     return err;
 }
 
-status_t MediaCodecSource::Puller::start(const sp<MetaData> &meta,
-        const sp<AMessage> &notify) {
+status_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, const sp<AMessage> &notify) {
     ALOGV("puller (%s) start", mIsAudio ? "audio" : "video");
     mLooper->start(
             false /* runOnCallingThread */,
@@ -133,41 +175,46 @@
 }
 
 void MediaCodecSource::Puller::stop() {
-    // Stop source from caller's thread instead of puller's looper.
-    // mSource->stop() is thread-safe, doing it outside the puller's
-    // looper allows us to at least stop if source gets stuck.
-    // If source gets stuck in read(), the looper would never
-    // be able to process the stop(), which could lead to ANR.
+    bool interrupt = false;
+    {
+        // mark stopping before actually reaching kWhatStop on the looper, so the pulling will
+        // stop.
+        Mutexed<Queue>::Locked queue(mQueue);
+        queue->mPulling = false;
+        interrupt = queue->mReadPendingSince && (queue->mReadPendingSince < ALooper::GetNowUs() - 1000000);
+        queue->flush(); // flush any unprocessed pulled buffers
+    }
 
-    ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video");
-    mSource->stop();
-    ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video");
+    if (interrupt) {
+        // call source->stop if read has been pending for over a second
+        // TODO: we should really call this if kWhatStop has not returned for more than a second.
+        mSource->stop();
+    }
+}
 
+void MediaCodecSource::Puller::stopSource() {
     (new AMessage(kWhatStop, this))->post();
 }
 
 void MediaCodecSource::Puller::pause() {
-    (new AMessage(kWhatPause, this))->post();
+    Mutexed<Queue>::Locked queue(mQueue);
+    queue->mPaused = true;
 }
 
 void MediaCodecSource::Puller::resume() {
-    (new AMessage(kWhatResume, this))->post();
+    Mutexed<Queue>::Locked queue(mQueue);
+    queue->mPaused = false;
 }
 
 void MediaCodecSource::Puller::schedulePull() {
-    sp<AMessage> msg = new AMessage(kWhatPull, this);
-    msg->setInt32("generation", mPullGeneration);
-    msg->post();
+    (new AMessage(kWhatPull, this))->post();
 }
 
 void MediaCodecSource::Puller::handleEOS() {
-    if (!mReachedEOS) {
-        ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video");
-        mReachedEOS = true;
-        sp<AMessage> notify = mNotify->dup();
-        notify->setPointer("accessUnit", NULL);
-        notify->post();
-    }
+    ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video");
+    sp<AMessage> msg = mNotify->dup();
+    msg->setInt32("eos", 1);
+    msg->post();
 }
 
 void MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) {
@@ -177,7 +224,10 @@
             sp<RefBase> obj;
             CHECK(msg->findObject("meta", &obj));
 
-            mReachedEOS = false;
+            {
+                Mutexed<Queue>::Locked queue(mQueue);
+                queue->mPulling = true;
+            }
 
             status_t err = mSource->start(static_cast<MetaData *>(obj.get()));
 
@@ -196,61 +246,52 @@
 
         case kWhatStop:
         {
-            ++mPullGeneration;
-
-            handleEOS();
+            mSource->stop();
             break;
         }
 
         case kWhatPull:
         {
-            int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-
-            if (generation != mPullGeneration) {
+            Mutexed<Queue>::Locked queue(mQueue);
+            queue->mReadPendingSince = ALooper::GetNowUs();
+            if (!queue->mPulling) {
+                handleEOS();
                 break;
             }
 
-            MediaBuffer *mbuf;
+            queue.unlock();
+            MediaBuffer *mbuf = NULL;
             status_t err = mSource->read(&mbuf);
+            queue.lock();
 
-            if (mPaused) {
-                if (err == OK) {
+            queue->mReadPendingSince = 0;
+            // if we need to discard buffer
+            if (!queue->mPulling || queue->mPaused || err != OK) {
+                if (mbuf != NULL) {
                     mbuf->release();
                     mbuf = NULL;
                 }
-
-                msg->post();
-                break;
-            }
-
-            if (err != OK) {
-                if (err == ERROR_END_OF_STREAM) {
+                if (queue->mPulling && err == OK) {
+                    msg->post(); // if simply paused, keep pulling source
+                } else if (err == ERROR_END_OF_STREAM) {
                     ALOGV("stream ended, mbuf %p", mbuf);
-                } else {
+                } else if (err != OK) {
                     ALOGE("error %d reading stream.", err);
                 }
-                handleEOS();
-            } else {
-                sp<AMessage> notify = mNotify->dup();
-
-                notify->setPointer("accessUnit", mbuf);
-                notify->post();
-
-                msg->post();
             }
-            break;
-        }
 
-        case kWhatPause:
-        {
-            mPaused = true;
-            break;
-        }
+            if (mbuf != NULL) {
+                queue->pushBuffer(mbuf);
+            }
 
-        case kWhatResume:
-        {
-            mPaused = false;
+            queue.unlock();
+
+            if (mbuf != NULL) {
+                mNotify->post();
+                msg->post();
+            } else {
+                handleEOS();
+            }
             break;
         }
 
@@ -259,6 +300,11 @@
     }
 }
 
+MediaCodecSource::Output::Output()
+    : mEncoderReachedEOS(false),
+      mErrorCode(OK) {
+}
+
 // static
 sp<MediaCodecSource> MediaCodecSource::Create(
         const sp<ALooper> &looper,
@@ -289,21 +335,7 @@
 
 status_t MediaCodecSource::stop() {
     sp<AMessage> msg = new AMessage(kWhatStop, mReflector);
-    status_t err = postSynchronouslyAndReturnError(msg);
-
-    // mPuller->stop() needs to be done outside MediaCodecSource's looper,
-    // as it contains a synchronous call to stop the underlying MediaSource,
-    // which often waits for all outstanding MediaBuffers to return, but
-    // MediaBuffers are only returned when MediaCodecSource looper gets
-    // to process them.
-
-    if (mPuller != NULL) {
-        ALOGI("puller (%s) stopping", mIsVideo ? "video" : "audio");
-        mPuller->stop();
-        ALOGI("puller (%s) stopped", mIsVideo ? "video" : "audio");
-    }
-
-    return err;
+    return postSynchronouslyAndReturnError(msg);
 }
 
 status_t MediaCodecSource::pause() {
@@ -318,18 +350,18 @@
 
 status_t MediaCodecSource::read(
         MediaBuffer** buffer, const ReadOptions* /* options */) {
-    Mutex::Autolock autolock(mOutputBufferLock);
+    Mutexed<Output>::Locked output(mOutput);
 
     *buffer = NULL;
-    while (mOutputBufferQueue.size() == 0 && !mEncoderReachedEOS) {
-        mOutputBufferCond.wait(mOutputBufferLock);
+    while (output->mBufferQueue.size() == 0 && !output->mEncoderReachedEOS) {
+        output.waitForCondition(output->mCond);
     }
-    if (!mEncoderReachedEOS) {
-        *buffer = *mOutputBufferQueue.begin();
-        mOutputBufferQueue.erase(mOutputBufferQueue.begin());
+    if (!output->mEncoderReachedEOS) {
+        *buffer = *output->mBufferQueue.begin();
+        output->mBufferQueue.erase(output->mBufferQueue.begin());
         return OK;
     }
-    return mErrorCode;
+    return output->mErrorCode;
 }
 
 void MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) {
@@ -357,8 +389,7 @@
       mGraphicBufferConsumer(consumer),
       mInputBufferTimeOffsetUs(0),
       mFirstSampleTimeUs(-1ll),
-      mEncoderReachedEOS(false),
-      mErrorCode(OK) {
+      mGeneration(0) {
     CHECK(mLooper != NULL);
 
     AString mime;
@@ -485,8 +516,11 @@
         return err;
     }
 
-    mEncoderReachedEOS = false;
-    mErrorCode = OK;
+    {
+        Mutexed<Output>::Locked output(mOutput);
+        output->mEncoderReachedEOS = false;
+        output->mErrorCode = OK;
+    }
 
     return OK;
 }
@@ -498,14 +532,6 @@
 
     mEncoder->release();
     mEncoder.clear();
-
-    while (!mInputBufferQueue.empty()) {
-        MediaBuffer *mbuf = *mInputBufferQueue.begin();
-        mInputBufferQueue.erase(mInputBufferQueue.begin());
-        if (mbuf != NULL) {
-            mbuf->release();
-        }
-    }
 }
 
 status_t MediaCodecSource::postSynchronouslyAndReturnError(
@@ -525,25 +551,32 @@
 }
 
 void MediaCodecSource::signalEOS(status_t err) {
-    if (!mEncoderReachedEOS) {
-        ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
-        {
-            Mutex::Autolock autoLock(mOutputBufferLock);
+    bool reachedEOS = false;
+    {
+        Mutexed<Output>::Locked output(mOutput);
+        reachedEOS = output->mEncoderReachedEOS;
+        if (!reachedEOS) {
+            ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
             // release all unread media buffers
-            for (List<MediaBuffer*>::iterator it = mOutputBufferQueue.begin();
-                    it != mOutputBufferQueue.end(); it++) {
+            for (List<MediaBuffer*>::iterator it = output->mBufferQueue.begin();
+                    it != output->mBufferQueue.end(); it++) {
                 (*it)->release();
             }
-            mOutputBufferQueue.clear();
-            mEncoderReachedEOS = true;
-            mErrorCode = err;
-            mOutputBufferCond.signal();
-        }
+            output->mBufferQueue.clear();
+            output->mEncoderReachedEOS = true;
+            output->mErrorCode = err;
+            output->mCond.signal();
 
-        releaseEncoder();
+            reachedEOS = true;
+            output.unlock();
+            releaseEncoder();
+        }
     }
-    if (mStopping && mEncoderReachedEOS) {
+
+    if (mStopping && reachedEOS) {
         ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
+        mPuller->stopSource();
+        ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
         // posting reply to everyone that's waiting
         List<sp<AReplyToken>>::iterator it;
         for (it = mStopReplyIDQueue.begin();
@@ -552,6 +585,7 @@
         }
         mStopReplyIDQueue.clear();
         mStopping = false;
+        ++mGeneration;
     }
 }
 
@@ -577,11 +611,8 @@
 }
 
 status_t MediaCodecSource::feedEncoderInputBuffers() {
-    while (!mInputBufferQueue.empty()
-            && !mAvailEncoderInputIndices.empty()) {
-        MediaBuffer* mbuf = *mInputBufferQueue.begin();
-        mInputBufferQueue.erase(mInputBufferQueue.begin());
-
+    MediaBuffer* mbuf = NULL;
+    while (!mAvailEncoderInputIndices.empty() && mPuller->readBuffer(&mbuf)) {
         size_t bufferIndex = *mAvailEncoderInputIndices.begin();
         mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
 
@@ -700,30 +731,19 @@
     switch (msg->what()) {
     case kWhatPullerNotify:
     {
-        MediaBuffer *mbuf;
-        CHECK(msg->findPointer("accessUnit", (void**)&mbuf));
-
-        if (mbuf == NULL) {
-            ALOGV("puller (%s) reached EOS",
-                    mIsVideo ? "video" : "audio");
+        int32_t eos = 0;
+        if (msg->findInt32("eos", &eos) && eos) {
+            ALOGV("puller (%s) reached EOS", mIsVideo ? "video" : "audio");
             signalEOS();
-        }
-
-        if (mEncoder == NULL) {
-            ALOGV("got msg '%s' after encoder shutdown.",
-                  msg->debugString().c_str());
-
-            if (mbuf != NULL) {
-                mbuf->release();
-            }
-
             break;
         }
 
-        mInputBufferQueue.push_back(mbuf);
+        if (mEncoder == NULL) {
+            ALOGV("got msg '%s' after encoder shutdown.", msg->debugString().c_str());
+            break;
+        }
 
         feedEncoderInputBuffers();
-
         break;
     }
     case kWhatEncoderActivity:
@@ -815,9 +835,9 @@
             mbuf->add_ref();
 
             {
-                Mutex::Autolock autoLock(mOutputBufferLock);
-                mOutputBufferQueue.push_back(mbuf);
-                mOutputBufferCond.signal();
+                Mutexed<Output>::Locked output(mOutput);
+                output->mBufferQueue.push_back(mbuf);
+                output->mCond.signal();
             }
 
             mEncoder->releaseOutputBuffer(index);
@@ -851,7 +871,7 @@
         sp<AReplyToken> replyID;
         CHECK(msg->senderAwaitsResponse(&replyID));
 
-        if (mEncoderReachedEOS) {
+        if (mOutput.lock()->mEncoderReachedEOS) {
             // if we already reached EOS, reply and return now
             ALOGI("encoder (%s) already stopped",
                     mIsVideo ? "video" : "audio");
@@ -869,14 +889,38 @@
         mStopping = true;
 
         // if using surface, signal source EOS and wait for EOS to come back.
-        // otherwise, release encoder and post EOS if haven't done already
+        // otherwise, stop puller (which also clears the input buffer queue)
+        // and wait for the EOS message. We cannot call source->stop() because
+        // the encoder may still be processing input buffers.
         if (mFlags & FLAG_USE_SURFACE_INPUT) {
             mEncoder->signalEndOfInputStream();
         } else {
-            signalEOS();
+            mPuller->stop();
         }
+
+        // complete stop even if encoder/puller stalled
+        sp<AMessage> timeoutMsg = new AMessage(kWhatStopStalled, mReflector);
+        timeoutMsg->setInt32("generation", mGeneration);
+        timeoutMsg->post(kStopTimeoutUs);
         break;
     }
+
+    case kWhatStopStalled:
+    {
+        int32_t generation;
+        CHECK(msg->findInt32("generation", &generation));
+        if (generation != mGeneration) {
+             break;
+        }
+
+        if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
+            ALOGV("source (%s) stopping", mIsVideo ? "video" : "audio");
+            mPuller->stopSource();
+            ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
+        }
+        signalEOS();
+    }
+
     case kWhatPause:
     {
         if (mFlags & FLAG_USE_SURFACE_INPUT) {
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 8809640..dd7f6b9 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -110,7 +110,8 @@
         // at the container mime type.
         // The cryptoPluginMode ensures that the extractor will actually
         // give us data in a call to MediaSource::read(), unlike its
-        // default mode that we use from AwesomePlayer.
+        // default mode that we used in AwesomePlayer.
+        // TODO: change default mode
         static_cast<WVMExtractor *>(mImpl.get())->setCryptoPluginMode(true);
     } else if (mImpl->getDrmFlag()) {
         // For all other drm content, we don't want to expose decrypted
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index e69890d..b1f69ce 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -25,8 +25,10 @@
 
 #include <binder/IServiceManager.h>
 #include <media/IMediaPlayerService.h>
+#include <media/IMediaCodecService.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/OMXClient.h>
+#include <cutils/properties.h>
 #include <utils/KeyedVector.h>
 
 #include "include/OMX.h"
@@ -34,10 +36,11 @@
 namespace android {
 
 struct MuxOMX : public IOMX {
-    MuxOMX(const sp<IOMX> &remoteOMX);
+    MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX);
     virtual ~MuxOMX();
 
-    virtual IBinder *onAsBinder() { return IInterface::asBinder(mRemoteOMX).get(); }
+    // TODO: does it matter which interface we return here?
+    virtual IBinder *onAsBinder() { return IInterface::asBinder(mMediaServerOMX).get(); }
 
     virtual bool livesLocally(node_id node, pid_t pid);
 
@@ -148,23 +151,39 @@
 private:
     mutable Mutex mLock;
 
-    sp<IOMX> mRemoteOMX;
+    sp<IOMX> mMediaServerOMX;
+    sp<IOMX> mMediaCodecOMX;
     sp<IOMX> mLocalOMX;
+    static bool sCodecProcessEnabled;
 
-    KeyedVector<node_id, bool> mIsLocalNode;
+    typedef enum {
+        LOCAL,
+        MEDIAPROCESS,
+        CODECPROCESS
+    } node_location;
+
+    KeyedVector<node_id, node_location> mNodeLocation;
 
     bool isLocalNode(node_id node) const;
     bool isLocalNode_l(node_id node) const;
     const sp<IOMX> &getOMX(node_id node) const;
     const sp<IOMX> &getOMX_l(node_id node) const;
 
-    static bool CanLiveLocally(const char *name);
+    static node_location getPreferredCodecLocation(const char *name);
 
     DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
 };
 
-MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
-    : mRemoteOMX(remoteOMX) {
+bool MuxOMX::sCodecProcessEnabled = true;
+
+MuxOMX::MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX)
+    : mMediaServerOMX(mediaServerOMX),
+      mMediaCodecOMX(mediaCodecOMX) {
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("media.stagefright.codecremote", value, NULL)
+            && (!strcmp("0", value) || !strcasecmp("false", value))) {
+        sCodecProcessEnabled = false;
+    }
 }
 
 MuxOMX::~MuxOMX() {
@@ -177,27 +196,50 @@
 }
 
 bool MuxOMX::isLocalNode_l(node_id node) const {
-    return mIsLocalNode.indexOfKey(node) >= 0;
+    return mNodeLocation.valueFor(node) == LOCAL;
 }
 
 // static
-bool MuxOMX::CanLiveLocally(const char *name) {
+MuxOMX::node_location MuxOMX::getPreferredCodecLocation(const char *name) {
+    ALOGI("ShouldRunInCodecProcess(%s)", name);
+    if (sCodecProcessEnabled) {
+        // all non-secure decoders plus OMX.google.* encoders can go in the codec process
+        if ((strcasestr(name, "decoder") && !strcasestr(name, "secure")) ||
+                !strncasecmp(name, "OMX.google.", 11)) {
+            return CODECPROCESS;
+        }
+        // everything else runs in the media server
+        return MEDIAPROCESS;
+    } else {
 #ifdef __LP64__
-    (void)name; // disable unused parameter warning
-    // 64 bit processes always run OMX remote on MediaServer
-    return false;
+        // 64 bit processes always run OMX remote on MediaServer
+        return MEDIAPROCESS;
 #else
-    // 32 bit processes run only OMX.google.* components locally
-    return !strncasecmp(name, "OMX.google.", 11);
+        // 32 bit processes run only OMX.google.* components locally
+        if (!strncasecmp(name, "OMX.google.", 11)) {
+            return LOCAL;
+        }
+        return MEDIAPROCESS;
 #endif
+    }
 }
 
 const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
-    return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
+    Mutex::Autolock autoLock(mLock);
+    return getOMX_l(node);
 }
 
 const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
-    return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
+    node_location loc = mNodeLocation.valueFor(node);
+    if (loc == LOCAL) {
+        return mLocalOMX;
+    } else if (loc == MEDIAPROCESS) {
+        return mMediaServerOMX;
+    } else if (loc == CODECPROCESS) {
+        return mMediaCodecOMX;
+    }
+    ALOGE("Couldn't determine node location for node %d: %d, using local", node, loc);
+    return mLocalOMX;
 }
 
 bool MuxOMX::livesLocally(node_id node, pid_t pid) {
@@ -221,13 +263,16 @@
 
     sp<IOMX> omx;
 
-    if (CanLiveLocally(name)) {
+    node_location loc = getPreferredCodecLocation(name);
+    if (loc == CODECPROCESS) {
+        omx = mMediaCodecOMX;
+    } else if (loc == MEDIAPROCESS) {
+        omx = mMediaServerOMX;
+    } else {
         if (mLocalOMX == NULL) {
             mLocalOMX = new OMX;
         }
         omx = mLocalOMX;
-    } else {
-        omx = mRemoteOMX;
     }
 
     status_t err = omx->allocateNode(name, observer, node);
@@ -236,9 +281,7 @@
         return err;
     }
 
-    if (omx == mLocalOMX) {
-        mIsLocalNode.add(*node, true);
-    }
+    mNodeLocation.add(*node, loc);
 
     return OK;
 }
@@ -252,7 +295,7 @@
         return err;
     }
 
-    mIsLocalNode.removeItem(node);
+    mNodeLocation.removeItem(node);
 
     return OK;
 }
@@ -352,7 +395,7 @@
         sp<IGraphicBufferProducer> *bufferProducer,
         sp<IGraphicBufferConsumer> *bufferConsumer) {
     // TODO: local or remote? Always use remote for now
-    return mRemoteOMX->createPersistentInputSurface(
+    return mMediaServerOMX->createPersistentInputSurface(
             bufferProducer, bufferConsumer);
 }
 
@@ -419,25 +462,36 @@
 
 status_t OMXClient::connect() {
     sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("media.player"));
-    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+    sp<IBinder> playerbinder = sm->getService(String16("media.player"));
+    sp<IMediaPlayerService> mediaservice = interface_cast<IMediaPlayerService>(playerbinder);
 
-    if (service.get() == NULL) {
+    if (mediaservice.get() == NULL) {
         ALOGE("Cannot obtain IMediaPlayerService");
         return NO_INIT;
     }
 
-    mOMX = service->getOMX();
-    if (mOMX.get() == NULL) {
-        ALOGE("Cannot obtain IOMX");
+    sp<IOMX> mediaServerOMX = mediaservice->getOMX();
+    if (mediaServerOMX.get() == NULL) {
+        ALOGE("Cannot obtain mediaserver IOMX");
         return NO_INIT;
     }
 
-    if (!mOMX->livesLocally(0 /* node */, getpid())) {
-        ALOGI("Using client-side OMX mux.");
-        mOMX = new MuxOMX(mOMX);
+    sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
+    sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
+
+    if (codecservice.get() == NULL) {
+        ALOGE("Cannot obtain IMediaCodecService");
+        return NO_INIT;
     }
 
+    sp<IOMX> mediaCodecOMX = codecservice->getOMX();
+    if (mediaCodecOMX.get() == NULL) {
+        ALOGE("Cannot obtain mediacodec IOMX");
+        return NO_INIT;
+    }
+
+    mOMX = new MuxOMX(mediaServerOMX, mediaCodecOMX);
+
     return OK;
 }
 
diff --git a/media/libstagefright/SimpleDecodingSource.cpp b/media/libstagefright/SimpleDecodingSource.cpp
new file mode 100644
index 0000000..04f9a88
--- /dev/null
+++ b/media/libstagefright/SimpleDecodingSource.cpp
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2016, 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 <gui/Surface.h>
+
+#include <media/ICrypto.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/SimpleDecodingSource.h>
+#include <media/stagefright/Utils.h>
+
+using namespace android;
+
+const int64_t kTimeoutWaitForOutputUs = 500000; // 0.5 seconds
+
+//static
+sp<SimpleDecodingSource> SimpleDecodingSource::Create(
+        const sp<IMediaSource> &source, uint32_t flags, const sp<ANativeWindow> &nativeWindow) {
+    sp<Surface> surface = static_cast<Surface*>(nativeWindow.get());
+    const char *mime = NULL;
+    sp<MetaData> meta = source->getFormat();
+    CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+    sp<AMessage> format = new AMessage;
+    convertMetaDataToMessage(source->getFormat(), &format);
+
+    Vector<AString> matchingCodecs;
+    MediaCodecList::findMatchingCodecs(
+            mime, false /* encoder */, flags, &matchingCodecs);
+
+    sp<ALooper> looper = new ALooper;
+    looper->setName("stagefright");
+    looper->start();
+
+    sp<MediaCodec> codec;
+
+    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
+        const AString &componentName = matchingCodecs[i];
+
+        ALOGV("Attempting to allocate codec '%s'", componentName.c_str());
+
+        codec = MediaCodec::CreateByComponentName(looper, componentName);
+        if (codec != NULL) {
+            ALOGI("Successfully allocated codec '%s'", componentName.c_str());
+
+            status_t err = codec->configure(format, surface, NULL /* crypto */, 0 /* flags */);
+            if (err == OK) {
+                err = codec->getOutputFormat(&format);
+            }
+            if (err == OK) {
+                return new SimpleDecodingSource(codec, source, looper, surface != NULL, format);
+            }
+
+            ALOGD("Failed to configure codec '%s'", componentName.c_str());
+            codec->release();
+            codec = NULL;
+        }
+    }
+
+    looper->stop();
+    ALOGE("No matching decoder! (mime: %s)", mime);
+    return NULL;
+}
+
+SimpleDecodingSource::SimpleDecodingSource(
+        const sp<MediaCodec> &codec, const sp<IMediaSource> &source, const sp<ALooper> &looper,
+        bool usingSurface, const sp<AMessage> &format)
+    : mCodec(codec),
+      mSource(source),
+      mLooper(looper),
+      mUsingSurface(usingSurface),
+      mProtectedState(format) {
+    mCodec->getName(&mComponentName);
+}
+
+SimpleDecodingSource::~SimpleDecodingSource() {
+    mCodec->release();
+    mLooper->stop();
+}
+
+status_t SimpleDecodingSource::start(MetaData *params) {
+    (void)params;
+    Mutexed<ProtectedState>::Locked me(mProtectedState);
+    if (me->mState != INIT) {
+        return -EINVAL;
+    }
+    status_t res = mCodec->start();
+    if (res == OK) {
+        res = mSource->start();
+    }
+
+    if (res == OK) {
+        me->mState = STARTED;
+        me->mQueuedInputEOS = false;
+        me->mGotOutputEOS = false;
+    } else {
+        me->mState = ERROR;
+    }
+
+    return res;
+}
+
+status_t SimpleDecodingSource::stop() {
+    Mutexed<ProtectedState>::Locked me(mProtectedState);
+    if (me->mState != STARTED) {
+        return -EINVAL;
+    }
+
+    // wait for any pending reads to complete
+    me->mState = STOPPING;
+    while (me->mReading) {
+        me.waitForCondition(me->mReadCondition);
+    }
+
+    status_t res1 = mCodec->stop();
+    if (res1 != OK) {
+        mCodec->release();
+    }
+    status_t res2 = mSource->stop();
+    if (res1 == OK && res2 == OK) {
+        me->mState = STOPPED;
+    } else {
+        me->mState = ERROR;
+    }
+    return res1 != OK ? res1 : res2;
+}
+
+sp<MetaData> SimpleDecodingSource::getFormat() {
+    Mutexed<ProtectedState>::Locked me(mProtectedState);
+    if (me->mState == STARTED || me->mState == INIT) {
+        sp<MetaData> meta = new MetaData();
+        convertMessageToMetaData(me->mFormat, meta);
+        return meta;
+    }
+    return NULL;
+}
+
+SimpleDecodingSource::ProtectedState::ProtectedState(const sp<AMessage> &format)
+    : mReading(false),
+      mFormat(format),
+      mState(INIT),
+      mQueuedInputEOS(false),
+      mGotOutputEOS(false) {
+}
+
+status_t SimpleDecodingSource::read(
+        MediaBuffer **buffer, const ReadOptions *options) {
+    *buffer = NULL;
+
+    Mutexed<ProtectedState>::Locked me(mProtectedState);
+    if (me->mState != STARTED) {
+        return ERROR_END_OF_STREAM;
+    }
+    me->mReading = true;
+
+    status_t res = doRead(me, buffer, options);
+
+    me.lock();
+    me->mReading = false;
+    if (me->mState != STARTED) {
+        me->mReadCondition.signal();
+    }
+
+    return res;
+}
+
+status_t SimpleDecodingSource::doRead(
+        Mutexed<ProtectedState>::Locked &me, MediaBuffer **buffer, const ReadOptions *options) {
+    // |me| is always locked on entry, but is allowed to be unlocked on exit
+    CHECK_EQ(me->mState, STARTED);
+
+    size_t out_ix, in_ix, out_offset, out_size;
+    int64_t out_pts;
+    uint32_t out_flags;
+    status_t res;
+
+    // flush codec on seek
+    IMediaSource::ReadOptions::SeekMode mode;
+    if (options != NULL && options->getSeekTo(&out_pts, &mode)) {
+        me->mQueuedInputEOS = false;
+        me->mGotOutputEOS = false;
+        mCodec->flush();
+    }
+
+    if (me->mGotOutputEOS) {
+        return ERROR_END_OF_STREAM;
+    }
+
+    for (int retries = 1; ++retries; ) {
+        // If we fill all available input buffers, we should expect that
+        // the codec produces at least one output buffer. Also, the codec
+        // should produce an output buffer in at most 1 seconds. Retry a
+        // few times nonetheless.
+        while (!me->mQueuedInputEOS) {
+            res = mCodec->dequeueInputBuffer(&in_ix, 0);
+            if (res == -EAGAIN) {
+                // no available input buffers
+                break;
+            }
+
+            sp<ABuffer> in_buffer;
+            if (res == OK) {
+                res = mCodec->getInputBuffer(in_ix, &in_buffer);
+            }
+
+            if (res != OK || in_buffer == NULL) {
+                ALOGW("[%s] could not get input buffer #%zu",
+                        mComponentName.c_str(), in_ix);
+                me->mState = ERROR;
+                return UNKNOWN_ERROR;
+            }
+
+            MediaBuffer *in_buf;
+            while (true) {
+                in_buf = NULL;
+                me.unlock();
+                res = mSource->read(&in_buf, options);
+                me.lock();
+                if (res != OK || me->mState != STARTED) {
+                    if (in_buf != NULL) {
+                        in_buf->release();
+                        in_buf = NULL;
+                    }
+
+                    // queue EOS
+                    me->mQueuedInputEOS = true;
+                    if (mCodec->queueInputBuffer(
+                                 in_ix, 0 /* offset */, 0 /* size */,
+                                 0 /* pts */, MediaCodec::BUFFER_FLAG_EOS) != OK) {
+                        ALOGI("[%s] failed to queue input EOS", mComponentName.c_str());
+                        me->mState = ERROR;
+                        return UNKNOWN_ERROR;
+                    }
+
+                    // don't stop on EOS, but report error or EOS on stop
+                    if (res != ERROR_END_OF_STREAM) {
+                        me->mState = ERROR;
+                        return res;
+                    }
+                    if (me->mState != STARTED) {
+                        return ERROR_END_OF_STREAM;
+                    }
+                    break;
+                }
+                if (in_buf == NULL) { // should not happen
+                    continue;
+                } else if (in_buf->range_length() != 0) {
+                    break;
+                }
+                in_buf->release();
+            }
+
+            if (in_buf != NULL) {
+                int64_t timestampUs = 0;
+                CHECK(in_buf->meta_data()->findInt64(kKeyTime, &timestampUs));
+                if (in_buf->range_length() > in_buffer->capacity()) {
+                    ALOGW("'%s' received %zu input bytes for buffer of size %zu",
+                            mComponentName.c_str(),
+                            in_buf->range_length(), in_buffer->capacity());
+                }
+                memcpy(in_buffer->base(), (uint8_t *)in_buf->data() + in_buf->range_offset(),
+                       min(in_buf->range_length(), in_buffer->capacity()));
+
+                res = mCodec->queueInputBuffer(
+                        in_ix, 0 /* offset */, in_buf->range_length(),
+                        timestampUs, 0 /* flags */);
+                if (res != OK) {
+                    ALOGI("[%s] failed to queue input buffer #%zu", mComponentName.c_str(), in_ix);
+                    me->mState = ERROR;
+                }
+                in_buf->release();
+            }
+        }
+
+        me.unlock();
+        res = mCodec->dequeueOutputBuffer(
+                &out_ix, &out_offset, &out_size, &out_pts,
+                &out_flags, kTimeoutWaitForOutputUs /* timeoutUs */);
+        me.lock();
+        // abort read on stop
+        if (me->mState != STARTED) {
+            if (res == OK) {
+                mCodec->releaseOutputBuffer(out_ix);
+            }
+            return ERROR_END_OF_STREAM;
+        }
+
+        if (res == -EAGAIN) {
+            ALOGD("[%s] did not produce an output buffer. retry count: %d",
+                  mComponentName.c_str(), retries);
+            continue;
+        } else if (res == INFO_FORMAT_CHANGED) {
+            if (mCodec->getOutputFormat(&me->mFormat) != OK) {
+                me->mState = ERROR;
+                res = UNKNOWN_ERROR;
+            }
+            return res;
+        } else if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
+            ALOGV("output buffers changed");
+            continue;
+        } else if (res != OK) {
+            me->mState = ERROR;
+            return res;
+        }
+
+        sp<ABuffer> out_buffer;
+        res = mCodec->getOutputBuffer(out_ix, &out_buffer);
+        if (res != OK) {
+            ALOGW("[%s] could not get output buffer #%zu",
+                    mComponentName.c_str(), out_ix);
+            me->mState = ERROR;
+            return UNKNOWN_ERROR;
+        }
+        if (out_flags & MediaCodec::BUFFER_FLAG_EOS) {
+            me->mGotOutputEOS = true;
+            // return EOS immediately if last buffer is empty
+            if (out_size == 0) {
+                mCodec->releaseOutputBuffer(out_ix);
+                return ERROR_END_OF_STREAM;
+            }
+        }
+
+        if (mUsingSurface && out_size > 0) {
+            *buffer = new MediaBuffer(0);
+            mCodec->renderOutputBufferAndRelease(out_ix);
+        } else {
+            *buffer = new MediaBuffer(out_size);
+            CHECK_LE(out_buffer->size(), (*buffer)->size());
+            memcpy((*buffer)->data(), out_buffer->data(), out_buffer->size());
+            (*buffer)->meta_data()->setInt64(kKeyTime, out_pts);
+            mCodec->releaseOutputBuffer(out_ix);
+        }
+        return OK;
+    }
+
+    return TIMED_OUT;
+}
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
deleted file mode 100644
index 7d15220..0000000
--- a/media/libstagefright/TimedEventQueue.cpp
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#undef __STRICT_ANSI__
-#define __STDINT_LIMITS
-#define __STDC_LIMIT_MACROS
-
-#include <inttypes.h>
-#include <stdint.h>
-#include <sys/prctl.h>
-#include <sys/time.h>
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "TimedEventQueue"
-#include <utils/Log.h>
-#include <utils/threads.h>
-
-#include "include/TimedEventQueue.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <binder/IServiceManager.h>
-#include <powermanager/PowerManager.h>
-#include <binder/IPCThreadState.h>
-#include <utils/CallStack.h>
-
-namespace android {
-
-static int64_t kWakelockMinDelay = 100000ll;  // 100ms
-
-TimedEventQueue::TimedEventQueue()
-    : mNextEventID(1),
-      mRunning(false),
-      mStopped(false),
-      mDeathRecipient(new PMDeathRecipient(this)),
-      mWakeLockCount(0) {
-}
-
-TimedEventQueue::~TimedEventQueue() {
-    stop();
-    if (mPowerManager != 0) {
-        sp<IBinder> binder = IInterface::asBinder(mPowerManager);
-        binder->unlinkToDeath(mDeathRecipient);
-    }
-}
-
-void TimedEventQueue::start() {
-    if (mRunning) {
-        return;
-    }
-
-    mStopped = false;
-
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
-    pthread_create(&mThread, &attr, ThreadWrapper, this);
-
-    pthread_attr_destroy(&attr);
-
-    mRunning = true;
-}
-
-void TimedEventQueue::stop(bool flush) {
-    if (!mRunning) {
-        return;
-    }
-
-    if (flush) {
-        postEventToBack(new StopEvent);
-    } else {
-        postTimedEvent(new StopEvent, INT64_MIN);
-    }
-
-    void *dummy;
-    pthread_join(mThread, &dummy);
-
-    // some events may be left in the queue if we did not flush and the wake lock
-    // must be released.
-    releaseWakeLock_l(true /*force*/);
-    mQueue.clear();
-
-    mRunning = false;
-}
-
-TimedEventQueue::event_id TimedEventQueue::postEvent(const sp<Event> &event) {
-    // Reserve an earlier timeslot an INT64_MIN to be able to post
-    // the StopEvent to the absolute head of the queue.
-    return postTimedEvent(event, INT64_MIN + 1);
-}
-
-TimedEventQueue::event_id TimedEventQueue::postEventToBack(
-        const sp<Event> &event) {
-    return postTimedEvent(event, INT64_MAX);
-}
-
-TimedEventQueue::event_id TimedEventQueue::postEventWithDelay(
-        const sp<Event> &event, int64_t delay_us) {
-    CHECK(delay_us >= 0);
-    return postTimedEvent(event, ALooper::GetNowUs() + delay_us);
-}
-
-TimedEventQueue::event_id TimedEventQueue::postTimedEvent(
-        const sp<Event> &event, int64_t realtime_us) {
-    Mutex::Autolock autoLock(mLock);
-
-    event->setEventID(mNextEventID++);
-
-    List<QueueItem>::iterator it = mQueue.begin();
-    while (it != mQueue.end() && realtime_us >= (*it).realtime_us) {
-        ++it;
-    }
-
-    QueueItem item;
-    item.event = event;
-    item.realtime_us = realtime_us;
-    item.has_wakelock = false;
-
-    if (it == mQueue.begin()) {
-        mQueueHeadChangedCondition.signal();
-    }
-
-    if (realtime_us > ALooper::GetNowUs() + kWakelockMinDelay) {
-        acquireWakeLock_l();
-        item.has_wakelock = true;
-    }
-    mQueue.insert(it, item);
-
-    mQueueNotEmptyCondition.signal();
-
-    return event->eventID();
-}
-
-static bool MatchesEventID(
-        void *cookie, const sp<TimedEventQueue::Event> &event) {
-    TimedEventQueue::event_id *id =
-        static_cast<TimedEventQueue::event_id *>(cookie);
-
-    if (event->eventID() != *id) {
-        return false;
-    }
-
-    *id = 0;
-
-    return true;
-}
-
-bool TimedEventQueue::cancelEvent(event_id id) {
-    if (id == 0) {
-        return false;
-    }
-
-    cancelEvents(&MatchesEventID, &id, true /* stopAfterFirstMatch */);
-
-    // if MatchesEventID found a match, it will have set id to 0
-    // (which is not a valid event_id).
-
-    return id == 0;
-}
-
-void TimedEventQueue::cancelEvents(
-        bool (*predicate)(void *cookie, const sp<Event> &event),
-        void *cookie,
-        bool stopAfterFirstMatch) {
-    Mutex::Autolock autoLock(mLock);
-
-    List<QueueItem>::iterator it = mQueue.begin();
-    while (it != mQueue.end()) {
-        if (!(*predicate)(cookie, (*it).event)) {
-            ++it;
-            continue;
-        }
-
-        if (it == mQueue.begin()) {
-            mQueueHeadChangedCondition.signal();
-        }
-
-        ALOGV("cancelling event %d", (*it).event->eventID());
-
-        (*it).event->setEventID(0);
-        if ((*it).has_wakelock) {
-            releaseWakeLock_l();
-        }
-        it = mQueue.erase(it);
-        if (stopAfterFirstMatch) {
-            return;
-        }
-    }
-}
-
-// static
-void *TimedEventQueue::ThreadWrapper(void *me) {
-
-    androidSetThreadPriority(0, ANDROID_PRIORITY_FOREGROUND);
-
-    static_cast<TimedEventQueue *>(me)->threadEntry();
-
-    return NULL;
-}
-
-void TimedEventQueue::threadEntry() {
-    prctl(PR_SET_NAME, (unsigned long)"TimedEventQueue", 0, 0, 0);
-
-    for (;;) {
-        int64_t now_us = 0;
-        sp<Event> event;
-        bool wakeLocked = false;
-
-        {
-            Mutex::Autolock autoLock(mLock);
-
-            if (mStopped) {
-                break;
-            }
-
-            while (mQueue.empty()) {
-                mQueueNotEmptyCondition.wait(mLock);
-            }
-
-            event_id eventID = 0;
-            for (;;) {
-                if (mQueue.empty()) {
-                    // The only event in the queue could have been cancelled
-                    // while we were waiting for its scheduled time.
-                    break;
-                }
-
-                List<QueueItem>::iterator it = mQueue.begin();
-                eventID = (*it).event->eventID();
-
-                now_us = ALooper::GetNowUs();
-                int64_t when_us = (*it).realtime_us;
-
-                int64_t delay_us;
-                if (when_us < 0 || when_us == INT64_MAX) {
-                    delay_us = 0;
-                } else {
-                    delay_us = when_us - now_us;
-                }
-
-                if (delay_us <= 0) {
-                    break;
-                }
-
-                static int64_t kMaxTimeoutUs = 10000000ll;  // 10 secs
-                bool timeoutCapped = false;
-                if (delay_us > kMaxTimeoutUs) {
-                    ALOGW("delay_us exceeds max timeout: %" PRId64 " us", delay_us);
-
-                    // We'll never block for more than 10 secs, instead
-                    // we will split up the full timeout into chunks of
-                    // 10 secs at a time. This will also avoid overflow
-                    // when converting from us to ns.
-                    delay_us = kMaxTimeoutUs;
-                    timeoutCapped = true;
-                }
-
-                status_t err = mQueueHeadChangedCondition.waitRelative(
-                        mLock, delay_us * 1000ll);
-
-                if (!timeoutCapped && err == -ETIMEDOUT) {
-                    // We finally hit the time this event is supposed to
-                    // trigger.
-                    now_us = ALooper::GetNowUs();
-                    break;
-                }
-            }
-
-            // The event w/ this id may have been cancelled while we're
-            // waiting for its trigger-time, in that case
-            // removeEventFromQueue_l will return NULL.
-            // Otherwise, the QueueItem will be removed
-            // from the queue and the referenced event returned.
-            event = removeEventFromQueue_l(eventID, &wakeLocked);
-        }
-
-        if (event != NULL) {
-            // Fire event with the lock NOT held.
-            event->fire(this, now_us);
-            if (wakeLocked) {
-                Mutex::Autolock autoLock(mLock);
-                releaseWakeLock_l();
-            }
-        }
-    }
-}
-
-sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l(
-        event_id id, bool *wakeLocked) {
-    for (List<QueueItem>::iterator it = mQueue.begin();
-         it != mQueue.end(); ++it) {
-        if ((*it).event->eventID() == id) {
-            sp<Event> event = (*it).event;
-            event->setEventID(0);
-            *wakeLocked = (*it).has_wakelock;
-            mQueue.erase(it);
-            return event;
-        }
-    }
-
-    ALOGW("Event %d was not found in the queue, already cancelled?", id);
-
-    return NULL;
-}
-
-void TimedEventQueue::acquireWakeLock_l()
-{
-    if (mWakeLockCount == 0) {
-        CHECK(mWakeLockToken == 0);
-        if (mPowerManager == 0) {
-            // use checkService() to avoid blocking if power service is not up yet
-            sp<IBinder> binder =
-                defaultServiceManager()->checkService(String16("power"));
-            if (binder == 0) {
-                ALOGW("cannot connect to the power manager service");
-            } else {
-                mPowerManager = interface_cast<IPowerManager>(binder);
-                binder->linkToDeath(mDeathRecipient);
-            }
-        }
-        if (mPowerManager != 0) {
-            sp<IBinder> binder = new BBinder();
-            int64_t token = IPCThreadState::self()->clearCallingIdentity();
-            status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
-                                                             binder,
-                                                             String16("TimedEventQueue"),
-                                                             String16("media"));    // not oneway
-            IPCThreadState::self()->restoreCallingIdentity(token);
-            if (status == NO_ERROR) {
-                mWakeLockToken = binder;
-                mWakeLockCount++;
-            }
-        }
-    } else {
-        mWakeLockCount++;
-    }
-}
-
-void TimedEventQueue::releaseWakeLock_l(bool force)
-{
-    if (mWakeLockCount == 0) {
-        return;
-    }
-    if (force) {
-        // Force wakelock release below by setting reference count to 1.
-        mWakeLockCount = 1;
-    }
-    if (--mWakeLockCount == 0) {
-        CHECK(mWakeLockToken != 0);
-        if (mPowerManager != 0) {
-            int64_t token = IPCThreadState::self()->clearCallingIdentity();
-            mPowerManager->releaseWakeLock(mWakeLockToken, 0);  // not oneway
-            IPCThreadState::self()->restoreCallingIdentity(token);
-        }
-        mWakeLockToken.clear();
-    }
-}
-
-void TimedEventQueue::clearPowerManager()
-{
-    Mutex::Autolock _l(mLock);
-    releaseWakeLock_l(true /*force*/);
-    mPowerManager.clear();
-}
-
-void TimedEventQueue::PMDeathRecipient::binderDied(
-        const wp<IBinder>& /* who */) {
-    mQueue->clearPowerManager();
-}
-
-}  // namespace android
-
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
deleted file mode 100644
index 1204ee8..0000000
--- a/media/libstagefright/include/AwesomePlayer.h
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef AWESOME_PLAYER_H_
-
-#define AWESOME_PLAYER_H_
-
-#include "HTTPBase.h"
-#include "TimedEventQueue.h"
-
-#include <media/AudioResamplerPublic.h>
-#include <media/MediaPlayerInterface.h>
-#include <media/IMediaExtractor.h>
-#include <media/stagefright/DataSource.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/TimeSource.h>
-#include <media/stagefright/MetaData.h>
-#include <utils/threads.h>
-#include <drm/DrmManagerClient.h>
-
-namespace android {
-
-class AudioPlayer;
-struct ClockEstimator;
-class IDataSource;
-class MediaBuffer;
-struct NuCachedSource2;
-class IGraphicBufferProducer;
-
-class DrmManagerClinet;
-class DecryptHandle;
-
-class TimedTextDriver;
-class WVMExtractor;
-
-struct AwesomeRenderer : public RefBase {
-    AwesomeRenderer() {}
-
-    virtual void render(MediaBuffer *buffer) = 0;
-
-private:
-    AwesomeRenderer(const AwesomeRenderer &);
-    AwesomeRenderer &operator=(const AwesomeRenderer &);
-};
-
-struct AwesomePlayer {
-    AwesomePlayer();
-    ~AwesomePlayer();
-
-    void setListener(const wp<MediaPlayerBase> &listener);
-    void setUID(uid_t uid);
-
-    status_t setDataSource(
-            const sp<IMediaHTTPService> &httpService,
-            const char *uri,
-            const KeyedVector<String8, String8> *headers = NULL);
-
-    status_t setDataSource(int fd, int64_t offset, int64_t length);
-
-    status_t setDataSource(const sp<IStreamSource> &source);
-
-    void reset();
-
-    status_t prepare();
-    status_t prepare_l();
-    status_t prepareAsync();
-    status_t prepareAsync_l();
-
-    status_t play();
-    status_t pause();
-
-    bool isPlaying() const;
-
-    status_t setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer);
-    void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink);
-    status_t setLooping(bool shouldLoop);
-
-    status_t getDuration(int64_t *durationUs);
-    status_t getPosition(int64_t *positionUs);
-
-    status_t setParameter(int key, const Parcel &request);
-    status_t getParameter(int key, Parcel *reply);
-    status_t setPlaybackSettings(const AudioPlaybackRate &rate);
-    status_t getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */);
-    status_t invoke(const Parcel &request, Parcel *reply);
-    status_t setCacheStatCollectFreq(const Parcel &request);
-
-    status_t seekTo(int64_t timeUs);
-
-    // This is a mask of MediaExtractor::Flags.
-    uint32_t flags() const;
-
-    void postAudioEOS(int64_t delayUs = 0ll);
-    void postAudioSeekComplete();
-    void postAudioTearDown();
-    status_t dump(int fd, const Vector<String16> &args) const;
-
-private:
-    friend struct AwesomeEvent;
-    friend struct PreviewPlayer;
-
-    enum {
-        PLAYING             = 0x01,
-        LOOPING             = 0x02,
-        FIRST_FRAME         = 0x04,
-        PREPARING           = 0x08,
-        PREPARED            = 0x10,
-        AT_EOS              = 0x20,
-        PREPARE_CANCELLED   = 0x40,
-        CACHE_UNDERRUN      = 0x80,
-        AUDIO_AT_EOS        = 0x0100,
-        VIDEO_AT_EOS        = 0x0200,
-        AUTO_LOOPING        = 0x0400,
-
-        // We are basically done preparing but are currently buffering
-        // sufficient data to begin playback and finish the preparation phase
-        // for good.
-        PREPARING_CONNECTED = 0x0800,
-
-        // We're triggering a single video event to display the first frame
-        // after the seekpoint.
-        SEEK_PREVIEW        = 0x1000,
-
-        AUDIO_RUNNING       = 0x2000,
-        AUDIOPLAYER_STARTED = 0x4000,
-
-        INCOGNITO           = 0x8000,
-
-        TEXT_RUNNING        = 0x10000,
-        TEXTPLAYER_INITIALIZED  = 0x20000,
-
-        SLOW_DECODER_HACK   = 0x40000,
-    };
-
-    mutable Mutex mLock;
-    Mutex mMiscStateLock;
-    mutable Mutex mStatsLock;
-    Mutex mAudioLock;
-
-    OMXClient mClient;
-    TimedEventQueue mQueue;
-    bool mQueueStarted;
-    wp<MediaPlayerBase> mListener;
-    bool mUIDValid;
-    uid_t mUID;
-
-    sp<ANativeWindow> mNativeWindow;
-    sp<MediaPlayerBase::AudioSink> mAudioSink;
-
-    SystemTimeSource mSystemTimeSource;
-    TimeSource *mTimeSource;
-
-    sp<IMediaHTTPService> mHTTPService;
-    String8 mUri;
-    KeyedVector<String8, String8> mUriHeaders;
-
-    sp<DataSource> mFileSource;
-
-    sp<IMediaSource> mVideoTrack;
-    sp<IMediaSource> mVideoSource;
-    sp<AwesomeRenderer> mVideoRenderer;
-    bool mVideoRenderingStarted;
-    bool mVideoRendererIsPreview;
-    int32_t mMediaRenderingStartGeneration;
-    int32_t mStartGeneration;
-
-    ssize_t mActiveAudioTrackIndex;
-    sp<IMediaSource> mAudioTrack;
-    sp<IMediaSource> mOmxSource;
-    sp<IMediaSource> mAudioSource;
-    AudioPlayer *mAudioPlayer;
-    AudioPlaybackRate mPlaybackSettings;
-    int64_t mDurationUs;
-
-    int32_t mDisplayWidth;
-    int32_t mDisplayHeight;
-    int32_t mVideoScalingMode;
-
-    uint32_t mFlags;
-    uint32_t mExtractorFlags;
-    uint32_t mSinceLastDropped;
-
-    int64_t mTimeSourceDeltaUs;
-    int64_t mVideoTimeUs;
-
-    enum SeekType {
-        NO_SEEK,
-        SEEK,
-        SEEK_VIDEO_ONLY
-    };
-    SeekType mSeeking;
-
-    bool mSeekNotificationSent;
-    int64_t mSeekTimeUs;
-
-    int64_t mBitrate;  // total bitrate of the file (in bps) or -1 if unknown.
-
-    bool mWatchForAudioSeekComplete;
-    bool mWatchForAudioEOS;
-
-    sp<TimedEventQueue::Event> mVideoEvent;
-    bool mVideoEventPending;
-    sp<TimedEventQueue::Event> mStreamDoneEvent;
-    bool mStreamDoneEventPending;
-    sp<TimedEventQueue::Event> mBufferingEvent;
-    bool mBufferingEventPending;
-    sp<TimedEventQueue::Event> mCheckAudioStatusEvent;
-    bool mAudioStatusEventPending;
-    sp<TimedEventQueue::Event> mVideoLagEvent;
-    bool mVideoLagEventPending;
-    sp<TimedEventQueue::Event> mAudioTearDownEvent;
-    bool mAudioTearDownEventPending;
-    sp<TimedEventQueue::Event> mAsyncPrepareEvent;
-    Condition mPreparedCondition;
-    bool mIsAsyncPrepare;
-    status_t mPrepareResult;
-    status_t mStreamDoneStatus;
-
-    void postVideoEvent_l(int64_t delayUs = -1);
-    void postBufferingEvent_l();
-    void postStreamDoneEvent_l(status_t status);
-    void postCheckAudioStatusEvent(int64_t delayUs);
-    void postVideoLagEvent_l();
-    void postAudioTearDownEvent(int64_t delayUs);
-
-    status_t play_l();
-
-    MediaBuffer *mVideoBuffer;
-
-    sp<ClockEstimator> mClockEstimator;
-    sp<HTTPBase> mConnectingDataSource;
-    sp<NuCachedSource2> mCachedSource;
-
-    DrmManagerClient *mDrmManagerClient;
-    sp<DecryptHandle> mDecryptHandle;
-
-    int64_t mLastVideoTimeUs;
-    TimedTextDriver *mTextDriver;
-    int32_t mSelectedTimedTextTrack;
-
-    sp<WVMExtractor> mWVMExtractor;
-    sp<IMediaExtractor> mExtractor;
-
-    status_t setDataSource_l(
-            const sp<IMediaHTTPService> &httpService,
-            const char *uri,
-            const KeyedVector<String8, String8> *headers = NULL);
-
-    status_t setDataSource_l(const sp<DataSource> &dataSource);
-    status_t setDataSource_l(const sp<IMediaExtractor> &extractor);
-    void reset_l();
-    status_t seekTo_l(int64_t timeUs);
-    status_t pause_l(bool at_eos = false);
-    void initRenderer_l();
-    void notifyVideoSize_l();
-    void seekAudioIfNecessary_l();
-
-    void cancelPlayerEvents(bool keepNotifications = false);
-
-    void setAudioSource(sp<IMediaSource> source);
-    status_t initAudioDecoder();
-
-
-    void setVideoSource(sp<IMediaSource> source);
-    status_t initVideoDecoder(uint32_t flags = 0);
-
-    void addTextSource_l(size_t trackIndex, const sp<IMediaSource>& source);
-
-    void onStreamDone();
-
-    void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0);
-
-    void onVideoEvent();
-    void onBufferingUpdate();
-    void onCheckAudioStatus();
-    void onPrepareAsyncEvent();
-    void abortPrepare(status_t err);
-    void finishAsyncPrepare_l();
-    void onVideoLagUpdate();
-    void onAudioTearDownEvent();
-
-    void beginPrepareAsync_l();
-
-    bool getCachedDuration_l(int64_t *durationUs, bool *eos);
-
-    status_t finishSetDataSource_l();
-
-    static bool ContinuePreparation(void *cookie);
-
-    bool getBitrate(int64_t *bitrate);
-
-    int64_t estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs);
-    void finishSeekIfNecessary(int64_t videoTimeUs);
-    void ensureCacheIsFetching_l();
-
-    void notifyIfMediaStarted_l();
-    void createAudioPlayer_l();
-    status_t startAudioPlayer_l(bool sendErrorNotification = true);
-
-    void shutdownVideoDecoder_l();
-    status_t setNativeWindow_l(const sp<ANativeWindow> &native);
-
-    bool isStreamingHTTP() const;
-    void sendCacheStats();
-    void checkDrmStatus(const sp<DataSource>& dataSource);
-
-    enum FlagMode {
-        SET,
-        CLEAR,
-        ASSIGN
-    };
-    void modifyFlags(unsigned value, FlagMode mode);
-
-    struct TrackStat {
-        String8 mMIME;
-        String8 mDecoderName;
-    };
-
-    // protected by mStatsLock
-    struct Stats {
-        int mFd;
-        String8 mURI;
-        int64_t mBitrate;
-
-        // FIXME:
-        // These two indices are just 0 or 1 for now
-        // They are not representing the actual track
-        // indices in the stream.
-        ssize_t mAudioTrackIndex;
-        ssize_t mVideoTrackIndex;
-
-        int64_t mNumVideoFramesDecoded;
-        int64_t mNumVideoFramesDropped;
-        int32_t mVideoWidth;
-        int32_t mVideoHeight;
-        uint32_t mFlags;
-        Vector<TrackStat> mTracks;
-    } mStats;
-
-    bool    mOffloadAudio;
-    bool    mAudioTearDown;
-    bool    mAudioTearDownWasPlaying;
-    int64_t mAudioTearDownPosition;
-
-    status_t setVideoScalingMode(int32_t mode);
-    status_t setVideoScalingMode_l(int32_t mode);
-    status_t getTrackInfo(Parcel* reply) const;
-
-    status_t selectAudioTrack_l(const sp<IMediaSource>& source, size_t trackIndex);
-
-    // when select is true, the given track is selected.
-    // otherwise, the given track is unselected.
-    status_t selectTrack(size_t trackIndex, bool select);
-
-    size_t countTracks() const;
-
-    AwesomePlayer(const AwesomePlayer &);
-    AwesomePlayer &operator=(const AwesomePlayer &);
-};
-
-}  // namespace android
-
-#endif  // AWESOME_PLAYER_H_
diff --git a/media/libstagefright/include/TimedEventQueue.h b/media/libstagefright/include/TimedEventQueue.h
deleted file mode 100644
index 890f7e8..0000000
--- a/media/libstagefright/include/TimedEventQueue.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef TIMED_EVENT_QUEUE_H_
-
-#define TIMED_EVENT_QUEUE_H_
-
-#include <pthread.h>
-
-#include <utils/List.h>
-#include <utils/RefBase.h>
-#include <utils/threads.h>
-#include <powermanager/IPowerManager.h>
-
-namespace android {
-
-struct TimedEventQueue {
-
-    typedef int32_t event_id;
-
-    struct Event : public RefBase {
-        Event()
-            : mEventID(0) {
-        }
-
-        virtual ~Event() {}
-
-        event_id eventID() {
-            return mEventID;
-        }
-
-    protected:
-        virtual void fire(TimedEventQueue *queue, int64_t now_us) = 0;
-
-    private:
-        friend struct TimedEventQueue;
-
-        event_id mEventID;
-
-        void setEventID(event_id id) {
-            mEventID = id;
-        }
-
-        Event(const Event &);
-        Event &operator=(const Event &);
-    };
-
-    class PMDeathRecipient : public IBinder::DeathRecipient {
-    public:
-                    PMDeathRecipient(TimedEventQueue *queue) : mQueue(queue) {}
-        virtual     ~PMDeathRecipient() {}
-
-        // IBinder::DeathRecipient
-        virtual     void        binderDied(const wp<IBinder>& who);
-
-    private:
-                    PMDeathRecipient(const PMDeathRecipient&);
-                    PMDeathRecipient& operator = (const PMDeathRecipient&);
-
-                    TimedEventQueue *mQueue;
-    };
-
-    TimedEventQueue();
-    ~TimedEventQueue();
-
-    // Start executing the event loop.
-    void start();
-
-    // Stop executing the event loop, if flush is false, any pending
-    // events are discarded, otherwise the queue will stop (and this call
-    // return) once all pending events have been handled.
-    void stop(bool flush = false);
-
-    // Posts an event to the front of the queue (after all events that
-    // have previously been posted to the front but before timed events).
-    event_id postEvent(const sp<Event> &event);
-
-    event_id postEventToBack(const sp<Event> &event);
-
-    // It is an error to post an event with a negative delay.
-    event_id postEventWithDelay(const sp<Event> &event, int64_t delay_us);
-
-    // If the event is to be posted at a time that has already passed,
-    // it will fire as soon as possible.
-    event_id postTimedEvent(const sp<Event> &event, int64_t realtime_us);
-
-    // Returns true iff event is currently in the queue and has been
-    // successfully cancelled. In this case the event will have been
-    // removed from the queue and won't fire.
-    bool cancelEvent(event_id id);
-
-    // Cancel any pending event that satisfies the predicate.
-    // If stopAfterFirstMatch is true, only cancels the first event
-    // satisfying the predicate (if any).
-    void cancelEvents(
-            bool (*predicate)(void *cookie, const sp<Event> &event),
-            void *cookie,
-            bool stopAfterFirstMatch = false);
-
-    static int64_t getRealTimeUs();
-
-    void clearPowerManager();
-
-private:
-    struct QueueItem {
-        sp<Event> event;
-        int64_t realtime_us;
-        bool has_wakelock;
-    };
-
-    struct StopEvent : public TimedEventQueue::Event {
-        virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
-            queue->mStopped = true;
-        }
-    };
-
-    pthread_t mThread;
-    List<QueueItem> mQueue;
-    Mutex mLock;
-    Condition mQueueNotEmptyCondition;
-    Condition mQueueHeadChangedCondition;
-    event_id mNextEventID;
-
-    bool mRunning;
-    bool mStopped;
-
-    sp<IPowerManager>       mPowerManager;
-    sp<IBinder>             mWakeLockToken;
-    const sp<PMDeathRecipient> mDeathRecipient;
-    uint32_t                mWakeLockCount;
-
-    static void *ThreadWrapper(void *me);
-    void threadEntry();
-
-    sp<Event> removeEventFromQueue_l(event_id id, bool *wakeLocked);
-
-    void acquireWakeLock_l();
-    void releaseWakeLock_l(bool force = false);
-
-    TimedEventQueue(const TimedEventQueue &);
-    TimedEventQueue &operator=(const TimedEventQueue &);
-};
-
-}  // namespace android
-
-#endif  // TIMED_EVENT_QUEUE_H_
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index ae3cb33..6132a2c 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -23,6 +23,7 @@
 #include "SoftOMXPlugin.h"
 
 #include <dlfcn.h>
+#include <fcntl.h>
 
 #include <media/stagefright/foundation/ADebug.h>
 
@@ -30,6 +31,29 @@
 
 OMXMaster::OMXMaster()
     : mVendorLibHandle(NULL) {
+
+    mProcessName[0] = 0;
+    if (mProcessName[0] == 0) {
+        pid_t pid = getpid();
+        char filename[20];
+        snprintf(filename, sizeof(filename), "/proc/%d/comm", pid);
+        int fd = open(filename, O_RDONLY);
+        if (fd < 0) {
+            ALOGW("couldn't determine process name");
+            sprintf(mProcessName, "<unknown>");
+        } else {
+            ssize_t len = read(fd, mProcessName, sizeof(mProcessName));
+            if (len < 2) {
+                ALOGW("couldn't determine process name");
+                sprintf(mProcessName, "<unknown>");
+            } else {
+                // the name is newline terminated, so erase the newline
+                mProcessName[len - 1] = 0;
+            }
+            close(fd);
+        }
+    }
+
     addVendorPlugin();
     addPlugin(new SoftOMXPlugin);
 }
@@ -123,6 +147,7 @@
         const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData,
         OMX_COMPONENTTYPE **component) {
+    ALOGI("makeComponentInstance(%s) in %s process", name, mProcessName);
     Mutex::Autolock autoLock(mLock);
 
     *component = NULL;
diff --git a/media/libstagefright/omx/OMXMaster.h b/media/libstagefright/omx/OMXMaster.h
index 6069741..3f9c0ca 100644
--- a/media/libstagefright/omx/OMXMaster.h
+++ b/media/libstagefright/omx/OMXMaster.h
@@ -50,6 +50,7 @@
             Vector<String8> *roles);
 
 private:
+    char mProcessName[16];
     Mutex mLock;
     List<OMXPluginBase *> mPlugins;
     KeyedVector<String8, OMXPluginBase *> mPluginByComponentName;
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 5159de3..6e21c14 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -27,7 +27,7 @@
 #include <binder/IServiceManager.h>
 #include <binder/MemoryDealer.h>
 #include <media/IMediaHTTPService.h>
-#include <media/IMediaPlayerService.h>
+#include <media/IMediaCodecService.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/DataSource.h>
@@ -57,8 +57,8 @@
 
 status_t Harness::initOMX() {
     sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("media.player"));
-    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+    sp<IBinder> binder = sm->getService(String16("media.codec"));
+    sp<IMediaCodecService> service = interface_cast<IMediaCodecService>(binder);
     mOMX = service->getOMX();
 
     return mOMX != 0 ? OK : NO_INIT;
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
index dfb3d9c..bdda19c 100644
--- a/media/libstagefright/rtsp/Android.mk
+++ b/media/libstagefright/rtsp/Android.mk
@@ -43,17 +43,18 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:=         \
-        rtp_test.cpp
+LOCAL_SRC_FILES := \
+	rtp_test.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
-	libstagefright liblog libutils libbinder libstagefright_foundation
+	libstagefright liblog libutils libbinder libstagefright_foundation libmedia
 
 LOCAL_STATIC_LIBRARIES := \
-        libstagefright_rtsp
+	libstagefright_rtsp
 
-LOCAL_C_INCLUDES:= \
+LOCAL_C_INCLUDES := \
 	frameworks/av/media/libstagefright \
+	frameworks/av/cmds/stagefright \
 	$(TOP)/frameworks/native/include/media/openmax
 
 LOCAL_CFLAGS += -Wno-multichar -Werror -Wall
diff --git a/media/libstagefright/rtsp/MyTransmitter.h b/media/libstagefright/rtsp/MyTransmitter.h
index 369f276..bf44aff 100644
--- a/media/libstagefright/rtsp/MyTransmitter.h
+++ b/media/libstagefright/rtsp/MyTransmitter.h
@@ -31,9 +31,10 @@
 
 #ifdef ANDROID
 #include "VideoSource.h"
-
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaCodecSource.h>
 #endif
 
 namespace android {
@@ -109,17 +110,19 @@
 
         sp<MediaSource> source = new VideoSource(width, height);
 
-        sp<MetaData> encMeta = new MetaData;
-        encMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
-        encMeta->setInt32(kKeyWidth, width);
-        encMeta->setInt32(kKeyHeight, height);
+        sp<AMessage> encMeta = new AMessage;
+        encMeta->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
+        encMeta->setInt32("width", width);
+        encMeta->setInt32("height", height);
+        encMeta->setInt32("frame-rate", 30);
+        encMeta->setInt32("bitrate", 256000);
+        encMeta->setInt32("i-frame-interval", 10);
 
-        OMXClient client;
-        client.connect();
+        sp<ALooper> encLooper = new ALooper;
+        encLooper->setName("rtsp_transmitter");
+        encLooper->start();
 
-        mEncoder = OMXCodec::Create(
-                client.interface(), encMeta,
-                true /* createEncoder */, source);
+        mEncoder = MediaCodecSource::Create(encLooper, encMeta, source);
 
         mEncoder->start();
 
diff --git a/media/libstagefright/rtsp/rtp_test.cpp b/media/libstagefright/rtsp/rtp_test.cpp
index d43cd2a..24f529b 100644
--- a/media/libstagefright/rtsp/rtp_test.cpp
+++ b/media/libstagefright/rtsp/rtp_test.cpp
@@ -20,13 +20,13 @@
 
 #include <binder/ProcessState.h>
 
+#include <media/stagefright/foundation/base64.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MetaData.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
-#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/SimpleDecodingSource.h>
 
 #include "ARTPSession.h"
 #include "ASessionDescription.h"
@@ -178,15 +178,8 @@
     CHECK_EQ(session->countTracks(), 1u);
     sp<MediaSource> source = session->trackAt(0);
 
-    OMXClient client;
-    CHECK_EQ(client.connect(), (status_t)OK);
-
-    sp<MediaSource> decoder = OMXCodec::Create(
-            client.interface(),
-            source->getFormat(), false /* createEncoder */,
-            source,
-            NULL,
-            0);  // OMXCodec::kPreferSoftwareCodecs);
+    sp<MediaSource> decoder = SimpleDecodingSource::Create(
+            source, 0 /* flags: ACodec::kPreferSoftwareCodecs */);
     CHECK(decoder != NULL);
 
     CHECK_EQ(decoder->start(), (status_t)OK);
@@ -213,7 +206,7 @@
             int64_t timeUs;
             CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
 
-            printf("decoder returned frame of size %d at time %.2f secs\n",
+            printf("decoder returned frame of size %zu at time %.2f secs\n",
                    buffer->range_length(), timeUs / 1E6);
         }
 #endif
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/PolicyConfigurableDomains.xml b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/PolicyConfigurableDomains.xml
index 4ac466e..8c3917a 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/PolicyConfigurableDomains.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/PolicyConfigurableDomains.xml
@@ -52,18 +52,21 @@
       <Configuration Name="BluetoothA2dp">
         <CompoundRule Type="All">
           <SelectionCriterionRule SelectionCriterion="ForceUseForMedia" MatchesWhen="IsNot" Value="ForceNoBtA2dp"/>
+          <SelectionCriterionRule SelectionCriterion="ForceUseForCommunication" MatchesWhen="IsNot" Value="ForceBtSco"/>
           <SelectionCriterionRule SelectionCriterion="AvailableOutputDevices" MatchesWhen="Includes" Value="BluetoothA2dp"/>
         </CompoundRule>
       </Configuration>
       <Configuration Name="BluetoothA2dpHeadphone">
         <CompoundRule Type="All">
           <SelectionCriterionRule SelectionCriterion="ForceUseForMedia" MatchesWhen="IsNot" Value="ForceNoBtA2dp"/>
+          <SelectionCriterionRule SelectionCriterion="ForceUseForCommunication" MatchesWhen="IsNot" Value="ForceBtSco"/>
           <SelectionCriterionRule SelectionCriterion="AvailableOutputDevices" MatchesWhen="Includes" Value="BluetoothA2dpHeadphones"/>
         </CompoundRule>
       </Configuration>
       <Configuration Name="BluetoothA2dpSpeaker">
         <CompoundRule Type="All">
           <SelectionCriterionRule SelectionCriterion="ForceUseForMedia" MatchesWhen="IsNot" Value="ForceNoBtA2dp"/>
+          <SelectionCriterionRule SelectionCriterion="ForceUseForCommunication" MatchesWhen="IsNot" Value="ForceBtSco"/>
           <SelectionCriterionRule SelectionCriterion="AvailableOutputDevices" MatchesWhen="Includes" Value="BluetoothA2dpSpeaker"/>
         </CompoundRule>
       </Configuration>
@@ -119,6 +122,7 @@
         <CompoundRule Type="All">
           <SelectionCriterionRule SelectionCriterion="AvailableOutputDevices" MatchesWhen="Includes" Value="Speaker"/>
           <SelectionCriterionRule SelectionCriterion="ForceUseForHdmiSystemAudio" MatchesWhen="IsNot" Value="ForceHdmiSystemEnforced"/>
+          <SelectionCriterionRule SelectionCriterion="ForceUseForCommunication" MatchesWhen="IsNot" Value="ForceBtSco"/>
         </CompoundRule>
       </Configuration>
       <Configuration Name="Default">
@@ -902,10 +906,7 @@
           <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="IsNot" Value="InCall"/>
           <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="IsNot" Value="InCommunication"/>
           <SelectionCriterionRule SelectionCriterion="ForceUseForMedia" MatchesWhen="IsNot" Value="ForceNoBtA2dp"/>
-          <CompoundRule Type="Any">
-            <SelectionCriterionRule SelectionCriterion="ForceUseForCommunication" MatchesWhen="Is" Value="ForceBtSco"/>
-            <SelectionCriterionRule SelectionCriterion="ForceUseForCommunication" MatchesWhen="Is" Value="ForceNone"/>
-          </CompoundRule>
+          <SelectionCriterionRule SelectionCriterion="ForceUseForCommunication" MatchesWhen="Is" Value="ForceNone"/>
         </CompoundRule>
       </Configuration>
       <Configuration Name="BluetoothA2dpHeadphones">
@@ -914,10 +915,7 @@
           <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="IsNot" Value="InCall"/>
           <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="IsNot" Value="InCommunication"/>
           <SelectionCriterionRule SelectionCriterion="ForceUseForMedia" MatchesWhen="IsNot" Value="ForceNoBtA2dp"/>
-          <CompoundRule Type="Any">
-            <SelectionCriterionRule SelectionCriterion="ForceUseForCommunication" MatchesWhen="Is" Value="ForceBtSco"/>
-            <SelectionCriterionRule SelectionCriterion="ForceUseForCommunication" MatchesWhen="Is" Value="ForceNone"/>
-          </CompoundRule>
+          <SelectionCriterionRule SelectionCriterion="ForceUseForCommunication" MatchesWhen="Is" Value="ForceNone"/>
         </CompoundRule>
       </Configuration>
       <Configuration Name="BluetoothA2dpSpeaker">
@@ -1314,10 +1312,10 @@
           <BitParameter Name="bluetooth_a2dp">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/bluetooth_a2dp_headphones">
-          <BitParameter Name="bluetooth_a2dp_headphones">1</BitParameter>
+          <BitParameter Name="bluetooth_a2dp_headphones">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/bluetooth_a2dp_speaker">
-          <BitParameter Name="bluetooth_a2dp_speaker">0</BitParameter>
+          <BitParameter Name="bluetooth_a2dp_speaker">1</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/hdmi">
           <BitParameter Name="hdmi">0</BitParameter>
@@ -1924,7 +1922,7 @@
           <BitParameter Name="line">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/strategies/phone/selected_output_devices/mask/speaker">
-          <BitParameter Name="speaker">0</BitParameter>
+          <BitParameter Name="speaker">1</BitParameter>
         </ConfigurableElement>
       </Configuration>
     </Settings>
@@ -8197,6 +8195,22 @@
       <ConfigurableElement Path="/Policy/policy/input_sources/hotword/applicable_input_device/mask/spdif"/>
       <ConfigurableElement Path="/Policy/policy/input_sources/hotword/applicable_input_device/mask/bluetooth_a2dp"/>
       <ConfigurableElement Path="/Policy/policy/input_sources/hotword/applicable_input_device/mask/loopback"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/in"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/communication"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/ambient"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/hdmi"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/telephony_rx"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/back_mic"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/remote_submix"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/anlg_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/dgtl_dock_headset"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/usb_accessory"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/fm_tuner"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/tv_tuner"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/line"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/spdif"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/bluetooth_a2dp"/>
+      <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/loopback"/>
       <ConfigurableElement Path="/Policy/policy/input_sources/fm_tuner/applicable_input_device/mask/in"/>
       <ConfigurableElement Path="/Policy/policy/input_sources/fm_tuner/applicable_input_device/mask/communication"/>
       <ConfigurableElement Path="/Policy/policy/input_sources/fm_tuner/applicable_input_device/mask/ambient"/>
@@ -8733,6 +8747,54 @@
         <ConfigurableElement Path="/Policy/policy/input_sources/hotword/applicable_input_device/mask/loopback">
           <BitParameter Name="loopback">0</BitParameter>
         </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/in">
+          <BitParameter Name="in">1</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/communication">
+          <BitParameter Name="communication">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/ambient">
+          <BitParameter Name="ambient">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/hdmi">
+          <BitParameter Name="hdmi">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/telephony_rx">
+          <BitParameter Name="telephony_rx">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/back_mic">
+          <BitParameter Name="back_mic">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/remote_submix">
+          <BitParameter Name="remote_submix">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/anlg_dock_headset">
+          <BitParameter Name="anlg_dock_headset">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/dgtl_dock_headset">
+          <BitParameter Name="dgtl_dock_headset">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/usb_accessory">
+          <BitParameter Name="usb_accessory">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/fm_tuner">
+          <BitParameter Name="fm_tuner">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/tv_tuner">
+          <BitParameter Name="tv_tuner">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/line">
+          <BitParameter Name="line">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/spdif">
+          <BitParameter Name="spdif">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/bluetooth_a2dp">
+          <BitParameter Name="bluetooth_a2dp">0</BitParameter>
+        </ConfigurableElement>
+        <ConfigurableElement Path="/Policy/policy/input_sources/unprocessed/applicable_input_device/mask/loopback">
+          <BitParameter Name="loopback">0</BitParameter>
+        </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/input_sources/fm_tuner/applicable_input_device/mask/in">
           <BitParameter Name="in">1</BitParameter>
         </ConfigurableElement>
@@ -8893,7 +8955,7 @@
           <BitParameter Name="bluetooth_a2dp">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/input_sources/mic/applicable_input_device/mask/wired_headset">
-          <BitParameter Name="wired_headset">1</BitParameter>
+          <BitParameter Name="wired_headset">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/input_sources/mic/applicable_input_device/mask/usb_device">
           <BitParameter Name="usb_device">0</BitParameter>
@@ -9439,7 +9501,7 @@
           <BitParameter Name="usb_device">0</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/input_sources/voice_communication/applicable_input_device/mask/builtin_mic">
-          <BitParameter Name="builtin_mic">0</BitParameter>
+          <BitParameter Name="builtin_mic">1</BitParameter>
         </ConfigurableElement>
         <ConfigurableElement Path="/Policy/policy/input_sources/voice_communication/applicable_input_device/mask/back_mic">
           <BitParameter Name="back_mic">0</BitParameter>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_input_source.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_input_source.pfw
index d4bc370..07a3c81 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_input_source.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_input_source.pfw
@@ -186,6 +186,23 @@
 				spdif = 0
 				bluetooth_a2dp = 0
 				loopback = 0
+			component: /Policy/policy/input_sources/unprocessed/applicable_input_device/mask
+				in = 1
+				communication = 0
+				ambient = 0
+				hdmi = 0
+				telephony_rx = 0
+				back_mic = 0
+				remote_submix = 0
+				anlg_dock_headset = 0
+				dgtl_dock_headset = 0
+				usb_accessory = 0
+				fm_tuner = 0
+				tv_tuner = 0
+				line = 0
+				spdif = 0
+				bluetooth_a2dp = 0
+				loopback = 0
 			component: /Policy/policy/input_sources/fm_tuner/applicable_input_device/mask
 				in = 1
 				communication = 0
@@ -239,7 +256,7 @@
 					bluetooth_sco_headset = 1
 				component: mic/applicable_input_device/mask/
 					bluetooth_a2dp = 0
-					wired_headset = 1
+					wired_headset = 0
 					usb_device = 0
 					builtin_mic = 0
 					bluetooth_sco_headset = 1
@@ -484,11 +501,14 @@
 				back_mic = 1
 
 		conf: Default
+			#
+			# Fallback on the default input device which can be builtin mic for example
+			#
 			component: /Policy/policy/input_sources/voice_communication/applicable_input_device/mask
 				bluetooth_sco_headset = 0
 				wired_headset = 0
 				usb_device = 0
-				builtin_mic = 0
+				builtin_mic = 1
 				back_mic = 0
 
 	domain: RemoteSubmix
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_strategy_media.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_strategy_media.pfw
index 38bede5..006ac60 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_strategy_media.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_strategy_media.pfw
@@ -34,6 +34,7 @@
 
 			conf: BluetoothA2dp
 				ForceUseForMedia IsNot ForceNoBtA2dp
+				ForceUseForCommunication IsNot ForceBtSco
 				AvailableOutputDevices Includes BluetoothA2dp
 
 				component: /Policy/policy/strategies/media/selected_output_devices/mask
@@ -53,6 +54,7 @@
 
 			conf: BluetoothA2dpHeadphone
 				ForceUseForMedia IsNot ForceNoBtA2dp
+				ForceUseForCommunication IsNot ForceBtSco
 				AvailableOutputDevices Includes BluetoothA2dpHeadphones
 
 				component: /Policy/policy/strategies/media/selected_output_devices/mask
@@ -72,6 +74,7 @@
 
 			conf: BluetoothA2dpSpeaker
 				ForceUseForMedia IsNot ForceNoBtA2dp
+				ForceUseForCommunication IsNot ForceBtSco
 				AvailableOutputDevices Includes BluetoothA2dpSpeaker
 
 				component: /Policy/policy/strategies/media/selected_output_devices/mask
@@ -263,6 +266,7 @@
 				# If hdmi system audio mode is on, remove speaker out of output list.
 				#
 				ForceUseForHdmiSystemAudio IsNot ForceHdmiSystemEnforced
+				ForceUseForCommunication IsNot ForceBtSco
 
 				component: /Policy/policy/strategies/media/selected_output_devices/mask
 					speaker = 1
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_strategy_phone.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_strategy_phone.pfw
index 7b01491..ae70914 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_strategy_phone.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/device_for_strategy_phone.pfw
@@ -92,9 +92,7 @@
 				TelephonyMode IsNot InCall
 				TelephonyMode IsNot InCommunication
 				ForceUseForMedia IsNot ForceNoBtA2dp
-				ANY
-					ForceUseForCommunication Is ForceBtSco
-					ForceUseForCommunication Is ForceNone
+				ForceUseForCommunication Is ForceNone
 
 				component: /Policy/policy/strategies/phone/selected_output_devices/mask
 					earpiece = 0
@@ -124,9 +122,7 @@
 				TelephonyMode IsNot InCall
 				TelephonyMode IsNot InCommunication
 				ForceUseForMedia IsNot ForceNoBtA2dp
-				ANY
-					ForceUseForCommunication Is ForceBtSco
-					ForceUseForCommunication Is ForceNone
+				ForceUseForCommunication Is ForceNone
 
 				component: /Policy/policy/strategies/phone/selected_output_devices/mask
 					earpiece = 0
@@ -166,8 +162,8 @@
 					bluetooth_sco_headset = 0
 					bluetooth_sco_carkit = 0
 					bluetooth_a2dp = 0
-					bluetooth_a2dp_headphones = 1
-					bluetooth_a2dp_speaker = 0
+					bluetooth_a2dp_headphones = 0
+					bluetooth_a2dp_speaker = 1
 					hdmi = 0
 					angl_dock_headset = 0
 					dgtl_dock_headset = 0
@@ -463,6 +459,9 @@
 					speaker = 1
 
 			conf: Default
+				#
+				# Fallback on default output device which can be speaker for example
+				#
 				component: /Policy/policy/strategies/phone/selected_output_devices/mask
 					earpiece = 0
 					wired_headset = 0
@@ -480,6 +479,6 @@
 					usb_device = 0
 					telephony_tx = 0
 					line = 0
-					speaker = 0
+					speaker = 1
 
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/volumes.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/volumes.pfw
index 7ac7d5f..7db4537 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/volumes.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/volumes.pfw
@@ -8,7 +8,7 @@
 			/Policy/policy/streams/alarm/applicable_volume_profile/volume_profile = alarm
 			/Policy/policy/streams/notification/applicable_volume_profile/volume_profile = notification
 			/Policy/policy/streams/bluetooth_sco/applicable_volume_profile/volume_profile = bluetooth_sco
-                        /Policy/policy/streams/enforced_audible/applicable_volume_profile/volume_profile = enforced_audible
+			/Policy/policy/streams/enforced_audible/applicable_volume_profile/volume_profile = enforced_audible
 			/Policy/policy/streams/tts/applicable_volume_profile/volume_profile = tts
 			/Policy/policy/streams/accessibility/applicable_volume_profile/volume_profile = accessibility
 			/Policy/policy/streams/rerouting/applicable_volume_profile/volume_profile = rerouting
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-CommonTypes.xml b/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-CommonTypes.xml
index cf7df60..6d6145a 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-CommonTypes.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem-CommonTypes.xml
@@ -28,7 +28,7 @@
             <BitParameter Name="usb_accessory" Size="1" Pos="13"/>
             <BitParameter Name="usb_device" Size="1" Pos="14"/>
             <BitParameter Name="remote_submix" Size="1" Pos="15"/>
-            <BitParameter Name="telephony_tx" Size="1" Pos="26"/>
+            <BitParameter Name="telephony_tx" Size="1" Pos="16"/>
             <BitParameter Name="line" Size="1" Pos="17"/>
             <BitParameter Name="hdmi_arc" Size="1" Pos="18"/>
             <BitParameter Name="spdif" Size="1" Pos="19"/>
@@ -109,8 +109,9 @@
             <BitParameter Name="voice_recognition" Size="1" Pos="6"/>
             <BitParameter Name="voice_communication" Size="1" Pos="7"/>
             <BitParameter Name="remote_submix" Size="1" Pos="8"/>
-            <BitParameter Name="fm_tuner" Size="1" Pos="9"/>
-            <BitParameter Name="hotword" Size="1" Pos="10"/>
+            <BitParameter Name="unprocessed" Size="1" Pos="9"/>
+            <BitParameter Name="fm_tuner" Size="1" Pos="10"/>
+            <BitParameter Name="hotword" Size="1" Pos="11"/>
         </BitParameterBlock>
     </ComponentType>
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem.xml
index f08d45f..e35511c 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/example/Structure/PolicySubsystem.xml
@@ -120,6 +120,8 @@
                                                   Mapping="Amend1:VoiceCommunication,Identifier:7"/>
             <Component Name="remote_submix" Type="InputSource"
                                             Mapping="Amend1:RemoteSubmix,Identifier:8"/>
+            <Component Name="unprocessed" Type="InputSource"
+                                            Mapping="Amend1:Unprocessed,Identifier:9"/>
             <Component Name="fm_tuner" Type="InputSource" Mapping="Amend1:FmTuner,Identifier:1998"/>
             <Component Name="hotword" Type="InputSource" Mapping="Amend1:Hotword,Identifier:1999"/>
         </ComponentType>
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 7d585c0..ed807c6 100755
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -106,10 +106,8 @@
 
 status_t Engine::initCheck()
 {
-    if (mPolicyParameterMgr != NULL && mPolicyParameterMgr->start() != NO_ERROR) {
+    if (mPolicyParameterMgr == NULL || mPolicyParameterMgr->start() != NO_ERROR) {
         ALOGE("%s: could not start Policy PFW", __FUNCTION__);
-        delete mPolicyParameterMgr;
-        mPolicyParameterMgr = NULL;
         return NO_INIT;
     }
     return (mApmObserver != NULL)? NO_ERROR : NO_INIT;
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
index 3e40a2b..cc4d4db 100755
--- a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "APM::AudioPolicyEngine/PFWWrapper"
+//#define LOG_NDEBUG 0
 
 #include "ParameterManagerWrapper.h"
 #include "audio_policy_criteria_conf.h"
@@ -88,7 +89,6 @@
               __FUNCTION__, gAudioPolicyCriteriaVendorConfFilePath,
               gAudioPolicyCriteriaConfFilePath);
     }
-    ALOGD("%s: ParameterManagerWrapper instantiated!", __FUNCTION__);
 }
 
 ParameterManagerWrapper::~ParameterManagerWrapper()
@@ -118,7 +118,7 @@
 void ParameterManagerWrapper::addCriterionType(const string &typeName, bool isInclusive)
 {
     ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) == mPolicyCriterionTypes.end(),
-                      "CriterionType " << typeName << " already added");
+                      "CriterionType %s already added", typeName.c_str());
     ALOGD("%s: Adding new criterionType %s", __FUNCTION__, typeName.c_str());
 
     mPolicyCriterionTypes[typeName] = mPfwConnector->createSelectionCriterionType(isInclusive);
@@ -130,7 +130,7 @@
     const string &literalValue)
 {
     ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) != mPolicyCriterionTypes.end(),
-                      "CriterionType " << typeName.c_str() << "not found");
+                      "CriterionType %s not found", typeName.c_str());
     ALOGV("%s: Adding new value pair (%d,%s) for criterionType %s", __FUNCTION__,
           numericValue, literalValue.c_str(), typeName.c_str());
     ISelectionCriterionTypeInterface *criterionType = mPolicyCriterionTypes[typeName];
@@ -224,8 +224,8 @@
 {
     parameterManagerElementSupported<T>();
     typename std::map<string, T *>::iterator it = elementsMap.find(name);
-    ALOG_ASSERT(it != elementsMap.end(), "Element " << name << " not found");
-    return it->second;
+    ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
+    return it != elementsMap.end() ? it->second : NULL;
 }
 
 template <typename T>
@@ -233,8 +233,8 @@
 {
     parameterManagerElementSupported<T>();
     typename std::map<string, T *>::const_iterator it = elementsMap.find(name);
-    ALOG_ASSERT(it != elementsMap.end(), "Element " << name << " not found");
-    return it->second;
+    ALOG_ASSERT(it != elementsMap.end(), "Element %s not found", name.c_str());
+    return it != elementsMap.end() ? it->second : NULL;
 }
 
 void ParameterManagerWrapper::loadCriteria(cnode *root)
@@ -254,8 +254,8 @@
 void ParameterManagerWrapper::addCriterion(const string &name, const string &typeName,
                               const string &defaultLiteralValue)
 {
-    ALOG_ASSERT(mPolicyCriteria.find(criterionName) == mPolicyCriteria.end(),
-                "Route Criterion " << criterionName << " already added");
+    ALOG_ASSERT(mPolicyCriteria.find(name) == mPolicyCriteria.end(),
+                "Route Criterion %s already added", name.c_str());
 
     ISelectionCriterionTypeInterface *criterionType =
             getElement<ISelectionCriterionTypeInterface>(typeName, mPolicyCriterionTypes);
@@ -278,7 +278,7 @@
     const char *criterionName = root->name;
 
     ALOG_ASSERT(mPolicyCriteria.find(criterionName) == mPolicyCriteria.end(),
-                      "Criterion " << criterionName << " already added");
+                      "Criterion %s already added", criterionName);
 
     string paramKeyName = "";
     string path = "";
@@ -335,7 +335,12 @@
 
 status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
 {
-    ISelectionCriterionInterface *criterion = mPolicyCriteria[gPhoneStateCriterionTag];
+    ISelectionCriterionInterface *criterion =
+            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+    if (criterion == NULL) {
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
+        return BAD_VALUE;
+    }
     if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
         return BAD_VALUE;
     }
@@ -348,6 +353,10 @@
 {
     const ISelectionCriterionInterface *criterion =
             getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+    if (criterion == NULL) {
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
+        return AUDIO_MODE_NORMAL;
+    }
     return static_cast<audio_mode_t>(criterion->getCriterionState());
 }
 
@@ -359,7 +368,12 @@
         return BAD_VALUE;
     }
 
-    ISelectionCriterionInterface *criterion = mPolicyCriteria[gForceUseCriterionTag[usage]];
+    ISelectionCriterionInterface *criterion =
+            getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
+    if (criterion == NULL) {
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
+        return BAD_VALUE;
+    }
     if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
         return BAD_VALUE;
     }
@@ -376,6 +390,10 @@
     }
     const ISelectionCriterionInterface *criterion =
             getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
+    if (criterion == NULL) {
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
+        return AUDIO_POLICY_FORCE_NONE;
+    }
     return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
 }
 
@@ -389,9 +407,10 @@
 
 status_t ParameterManagerWrapper::setAvailableInputDevices(audio_devices_t inputDevices)
 {
-    ISelectionCriterionInterface *criterion = mPolicyCriteria[gInputDeviceCriterionTag];
+    ISelectionCriterionInterface *criterion =
+            getElement<ISelectionCriterionInterface>(gInputDeviceCriterionTag, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for input devices", __FUNCTION__);
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionTag.c_str());
         return DEAD_OBJECT;
     }
     criterion->setCriterionState(inputDevices & ~AUDIO_DEVICE_BIT_IN);
@@ -401,9 +420,10 @@
 
 status_t ParameterManagerWrapper::setAvailableOutputDevices(audio_devices_t outputDevices)
 {
-    ISelectionCriterionInterface *criterion = mPolicyCriteria[gOutputDeviceCriterionTag];
+    ISelectionCriterionInterface *criterion =
+            getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionTag, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for output devices", __FUNCTION__);
+        ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionTag.c_str());
         return DEAD_OBJECT;
     }
     criterion->setCriterionState(outputDevices);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ad2ad69..ec70ed4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1809,6 +1809,7 @@
         mpClientInterface->closeInput(mInputs.keyAt(input_index));
     }
     mInputs.clear();
+    SoundTrigger::setCaptureState(false);
     nextAudioPortGeneration();
 
     if (patchRemoved) {
@@ -5183,12 +5184,13 @@
         reply = mpClientInterface->getParameters(ioHandle,
                                                  String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS));
         ALOGV("%s: supported formats %s", __FUNCTION__, reply.string());
-        value = strpbrk((char *)reply.string(), "=");
-        if (value == NULL) {
+        AudioParameter repliedParameters(reply);
+        if (repliedParameters.get(
+                String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS), reply) != NO_ERROR) {
             ALOGE("%s: failed to retrieve format, bailing out", __FUNCTION__);
             return;
         }
-        profiles.setFormats(formatsFromString(value + 1));
+        profiles.setFormats(formatsFromString(reply.string()));
     }
     const FormatVector &supportedFormats = profiles.getSupportedFormats();
 
@@ -5204,9 +5206,10 @@
                                                      requestedParameters.toString() + ";" +
                                                      AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES);
             ALOGV("%s: supported sampling rates %s", __FUNCTION__, reply.string());
-            value = strpbrk((char *)reply.string(), "=");
-            if (value != NULL) {
-                samplingRates = samplingRatesFromString(value + 1);
+            AudioParameter repliedParameters(reply);
+            if (repliedParameters.get(
+                    String8(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES), reply) == NO_ERROR) {
+                samplingRates = samplingRatesFromString(reply.string());
             }
         }
         if (profiles.hasDynamicChannelsFor(format)) {
@@ -5214,9 +5217,10 @@
                                                      requestedParameters.toString() + ";" +
                                                      AUDIO_PARAMETER_STREAM_SUP_CHANNELS);
             ALOGV("%s: supported channel masks %s", __FUNCTION__, reply.string());
-            value = strpbrk((char *)reply.string(), "=");
-            if (value != NULL) {
-                channelMasks = channelMasksFromString(value + 1);
+            AudioParameter repliedParameters(reply);
+            if (repliedParameters.get(
+                    String8(AUDIO_PARAMETER_STREAM_SUP_CHANNELS), reply) == NO_ERROR) {
+                channelMasks = channelMasksFromString(reply.string());
             }
         }
         profiles.addProfileFromHal(new AudioProfile(format, channelMasks, samplingRates));
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 6aeab98..8ab9a65 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -295,9 +295,8 @@
     // If preview has been already started, register preview buffers now.
     if (mHardware->previewEnabled()) {
         if (window != 0) {
-            native_window_set_scaling_mode(window.get(),
-                    NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
-            native_window_set_buffers_transform(window.get(), mOrientation);
+            mHardware->setPreviewScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+            mHardware->setPreviewTransform(mOrientation);
             result = mHardware->setPreviewWindow(window);
         }
     }
@@ -404,10 +403,9 @@
     }
 
     if (mPreviewWindow != 0) {
-        native_window_set_scaling_mode(mPreviewWindow.get(),
-                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
-        native_window_set_buffers_transform(mPreviewWindow.get(),
-                mOrientation);
+        mHardware->setPreviewScalingMode(
+            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+        mHardware->setPreviewTransform(mOrientation);
     }
     mHardware->setPreviewWindow(mPreviewWindow);
     result = mHardware->startPreview();
@@ -641,8 +639,7 @@
         if (mOrientation != orientation) {
             mOrientation = orientation;
             if (mPreviewWindow != 0) {
-                native_window_set_buffers_transform(mPreviewWindow.get(),
-                        mOrientation);
+                mHardware->setPreviewTransform(mOrientation);
             }
         }
         return OK;
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 7f14cd4..0fe76e5 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -73,10 +73,18 @@
 
 class CameraHardwareInterface : public virtual RefBase {
 public:
-    CameraHardwareInterface(const char *name)
+    CameraHardwareInterface(const char *name):
+            mDevice(nullptr),
+            mName(name),
+            mPreviewScalingMode(NOT_SET),
+            mPreviewTransform(NOT_SET),
+            mPreviewWidth(NOT_SET),
+            mPreviewHeight(NOT_SET),
+            mPreviewFormat(NOT_SET),
+            mPreviewUsage(0),
+            mPreviewSwapInterval(NOT_SET),
+            mPreviewCrop{NOT_SET,NOT_SET,NOT_SET,NOT_SET}
     {
-        mDevice = 0;
-        mName = name;
     }
 
     ~CameraHardwareInterface()
@@ -118,9 +126,16 @@
     status_t setPreviewWindow(const sp<ANativeWindow>& buf)
     {
         ALOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get());
-
         if (mDevice->ops->set_preview_window) {
             mPreviewWindow = buf;
+            if (buf != nullptr) {
+                if (mPreviewScalingMode != NOT_SET) {
+                    setPreviewScalingMode(mPreviewScalingMode);
+                }
+                if (mPreviewTransform != NOT_SET) {
+                    setPreviewTransform(mPreviewTransform);
+                }
+            }
             mHalPreviewWindow.user = this;
             ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__,
                     &mHalPreviewWindow, mHalPreviewWindow.user);
@@ -130,6 +145,27 @@
         return INVALID_OPERATION;
     }
 
+    status_t setPreviewScalingMode(int scalingMode)
+    {
+        int rc = OK;
+        mPreviewScalingMode = scalingMode;
+        if (mPreviewWindow != nullptr) {
+            rc = native_window_set_scaling_mode(mPreviewWindow.get(),
+                    scalingMode);
+        }
+        return rc;
+    }
+
+    status_t setPreviewTransform(int transform) {
+        int rc = OK;
+        mPreviewTransform = transform;
+        if (mPreviewWindow != nullptr) {
+            rc = native_window_set_buffers_transform(mPreviewWindow.get(),
+                    mPreviewTransform);
+        }
+        return rc;
+    }
+
     /** Set the notification and data callbacks */
     void setCallbacks(notify_callback notify_cb,
                       data_callback data_cb,
@@ -569,6 +605,8 @@
         return __this->mPreviewWindow.get();
     }
 #define anw(n) __to_anw(((struct camera_preview_window *)n)->user)
+#define hwi(n) reinterpret_cast<CameraHardwareInterface *>(\
+        ((struct camera_preview_window *)n)->user)
 
     static int __dequeue_buffer(struct preview_stream_ops* w,
                                 buffer_handle_t** buffer, int *stride)
@@ -617,6 +655,44 @@
     static int __set_buffer_count(struct preview_stream_ops* w, int count)
     {
         ANativeWindow *a = anw(w);
+
+        if (a != nullptr) {
+            // Workaround for b/27039775
+            // Previously, setting the buffer count would reset the buffer
+            // queue's flag that allows for all buffers to be dequeued on the
+            // producer side, instead of just the producer's declared max count,
+            // if no filled buffers have yet been queued by the producer.  This
+            // reset no longer happens, but some HALs depend on this behavior,
+            // so it needs to be maintained for HAL backwards compatibility.
+            // Simulate the prior behavior by disconnecting/reconnecting to the
+            // window and setting the values again.  This has the drawback of
+            // actually causing memory reallocation, which may not have happened
+            // in the past.
+            CameraHardwareInterface *hw = hwi(w);
+            native_window_api_disconnect(a, NATIVE_WINDOW_API_CAMERA);
+            native_window_api_connect(a, NATIVE_WINDOW_API_CAMERA);
+            if (hw->mPreviewScalingMode != NOT_SET) {
+                native_window_set_scaling_mode(a, hw->mPreviewScalingMode);
+            }
+            if (hw->mPreviewTransform != NOT_SET) {
+                native_window_set_buffers_transform(a, hw->mPreviewTransform);
+            }
+            if (hw->mPreviewWidth != NOT_SET) {
+                native_window_set_buffers_dimensions(a,
+                        hw->mPreviewWidth, hw->mPreviewHeight);
+                native_window_set_buffers_format(a, hw->mPreviewFormat);
+            }
+            if (hw->mPreviewUsage != 0) {
+                native_window_set_usage(a, hw->mPreviewUsage);
+            }
+            if (hw->mPreviewSwapInterval != NOT_SET) {
+                a->setSwapInterval(a, hw->mPreviewSwapInterval);
+            }
+            if (hw->mPreviewCrop.left != NOT_SET) {
+                native_window_set_crop(a, &(hw->mPreviewCrop));
+            }
+        }
+
         return native_window_set_buffer_count(a, count);
     }
 
@@ -625,7 +701,10 @@
     {
         int rc;
         ANativeWindow *a = anw(w);
-
+        CameraHardwareInterface *hw = hwi(w);
+        hw->mPreviewWidth = width;
+        hw->mPreviewHeight = height;
+        hw->mPreviewFormat = format;
         rc = native_window_set_buffers_dimensions(a, width, height);
         if (!rc) {
             rc = native_window_set_buffers_format(a, format);
@@ -637,12 +716,12 @@
                       int left, int top, int right, int bottom)
     {
         ANativeWindow *a = anw(w);
-        android_native_rect_t crop;
-        crop.left = left;
-        crop.top = top;
-        crop.right = right;
-        crop.bottom = bottom;
-        return native_window_set_crop(a, &crop);
+        CameraHardwareInterface *hw = hwi(w);
+        hw->mPreviewCrop.left = left;
+        hw->mPreviewCrop.top = top;
+        hw->mPreviewCrop.right = right;
+        hw->mPreviewCrop.bottom = bottom;
+        return native_window_set_crop(a, &(hw->mPreviewCrop));
     }
 
     static int __set_timestamp(struct preview_stream_ops *w,
@@ -654,12 +733,16 @@
     static int __set_usage(struct preview_stream_ops* w, int usage)
     {
         ANativeWindow *a = anw(w);
+        CameraHardwareInterface *hw = hwi(w);
+        hw->mPreviewUsage = usage;
         return native_window_set_usage(a, usage);
     }
 
     static int __set_swap_interval(struct preview_stream_ops *w, int interval)
     {
         ANativeWindow *a = anw(w);
+        CameraHardwareInterface *hw = hwi(w);
+        hw->mPreviewSwapInterval = interval;
         return a->setSwapInterval(a, interval);
     }
 
@@ -701,6 +784,17 @@
     data_callback           mDataCb;
     data_callback_timestamp mDataCbTimestamp;
     void *mCbUser;
+
+    // Cached values for preview stream parameters
+    static const int NOT_SET = -1;
+    int mPreviewScalingMode;
+    int mPreviewTransform;
+    int mPreviewWidth;
+    int mPreviewHeight;
+    int mPreviewFormat;
+    int mPreviewUsage;
+    int mPreviewSwapInterval;
+    android_native_rect_t mPreviewCrop;
 };
 
 };  // namespace android
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
new file mode 100644
index 0000000..239b4e1
--- /dev/null
+++ b/services/mediacodec/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH := $(call my-dir)
+
+# service library
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := MediaCodecService.cpp
+LOCAL_SHARED_LIBRARIES := libmedia libbinder libutils liblog libstagefright_omx
+LOCAL_C_INCLUDES := \
+    $(TOP)/frameworks/av/media/libstagefright \
+    $(TOP)/frameworks/native/include/media/openmax
+LOCAL_MODULE:= libmediacodecservice
+LOCAL_32_BIT_ONLY := true
+include $(BUILD_SHARED_LIBRARY)
+
+
+# service executable
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := main_codecservice.cpp
+LOCAL_SHARED_LIBRARIES := libmedia libmediacodecservice libbinder libutils liblog
+LOCAL_C_INCLUDES := \
+    $(TOP)/frameworks/av/media/libstagefright \
+    $(TOP)/frameworks/native/include/media/openmax
+LOCAL_MODULE:= mediacodec
+LOCAL_32_BIT_ONLY := true
+LOCAL_INIT_RC := mediacodec.rc
+include $(BUILD_EXECUTABLE)
+
+
diff --git a/services/mediacodec/MODULE_LICENSE_APACHE2 b/services/mediacodec/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/services/mediacodec/MODULE_LICENSE_APACHE2
diff --git a/services/mediacodec/MediaCodecService.cpp b/services/mediacodec/MediaCodecService.cpp
new file mode 100644
index 0000000..fc1e5d9
--- /dev/null
+++ b/services/mediacodec/MediaCodecService.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "MediaCodecService"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "MediaCodecService.h"
+
+namespace android {
+
+sp<IOMX> MediaCodecService::getOMX() {
+
+    Mutex::Autolock autoLock(mLock);
+
+    if (mOMX.get() == NULL) {
+        mOMX = new OMX;
+    }
+
+    return mOMX;
+}
+
+
+status_t MediaCodecService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+        uint32_t flags)
+{
+    return BnMediaCodecService::onTransact(code, data, reply, flags);
+}
+
+}   // namespace android
diff --git a/services/mediacodec/MediaCodecService.h b/services/mediacodec/MediaCodecService.h
new file mode 100644
index 0000000..d64debb
--- /dev/null
+++ b/services/mediacodec/MediaCodecService.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_MEDIA_CODEC_SERVICE_H
+#define ANDROID_MEDIA_CODEC_SERVICE_H
+
+#include <binder/BinderService.h>
+#include <media/IMediaCodecService.h>
+#include <include/OMX.h>
+
+namespace android {
+
+class MediaCodecService : public BinderService<MediaCodecService>, public BnMediaCodecService
+{
+    friend class BinderService<MediaCodecService>;    // for MediaCodecService()
+public:
+    MediaCodecService() : BnMediaCodecService() { }
+    virtual ~MediaCodecService() { }
+    virtual void onFirstRef() { }
+
+    static const char*  getServiceName() { return "media.codec"; }
+
+    virtual sp<IOMX>    getOMX();
+
+    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                                uint32_t flags);
+
+private:
+    Mutex               mLock;
+    sp<IOMX>            mOMX;
+};
+
+}   // namespace android
+
+#endif  // ANDROID_MEDIA_CODEC_SERVICE_H
diff --git a/services/mediacodec/NOTICE b/services/mediacodec/NOTICE
new file mode 100644
index 0000000..34bdaf1
--- /dev/null
+++ b/services/mediacodec/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2015, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
new file mode 100644
index 0000000..aedf0c3
--- /dev/null
+++ b/services/mediacodec/main_codecservice.cpp
@@ -0,0 +1,45 @@
+/*
+**
+** Copyright 2015, 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.
+*/
+
+#define LOG_TAG "mediacodec"
+//#define LOG_NDEBUG 0
+
+#include <fcntl.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+// from LOCAL_C_INCLUDES
+#include "MediaCodecService.h"
+
+using namespace android;
+
+int main(int argc __unused, char** argv)
+{
+    ALOGI("@@@ mediacodecservice starting");
+    signal(SIGPIPE, SIG_IGN);
+
+    strcpy(argv[0], "media.codec");
+    sp<ProcessState> proc(ProcessState::self());
+    sp<IServiceManager> sm = defaultServiceManager();
+    MediaCodecService::instantiate();
+    ProcessState::self()->startThreadPool();
+    IPCThreadState::self()->joinThreadPool();
+}
diff --git a/services/mediacodec/mediacodec.rc b/services/mediacodec/mediacodec.rc
new file mode 100644
index 0000000..e8df7be
--- /dev/null
+++ b/services/mediacodec/mediacodec.rc
@@ -0,0 +1,5 @@
+service mediacodec /system/bin/mediacodec
+    class main
+    user mediacodec
+    group camera drmrpc mediadrm
+    ioprio rt 4