Merge "Enable full floating point path in AudioMixer"
diff --git a/camera/Android.mk b/camera/Android.mk
index da5ac59..df7279f 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -35,6 +35,7 @@
 	camera2/ICameraDeviceUser.cpp \
 	camera2/ICameraDeviceCallbacks.cpp \
 	camera2/CaptureRequest.cpp \
+	camera2/OutputConfiguration.cpp \
 	ProCamera.cpp \
 	CameraBase.cpp \
 	CameraUtils.cpp \
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 85f44f0..3a9fb4c 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -55,7 +55,7 @@
     if (camera->connect(c) == NO_ERROR) {
         c->mStatus = NO_ERROR;
         c->mCamera = camera;
-        camera->asBinder()->linkToDeath(c);
+        IInterface::asBinder(camera)->linkToDeath(c);
         return c;
     }
     return 0;
@@ -93,7 +93,7 @@
                                         clientUid, /*out*/c->mCamera);
     }
     if (status == OK && c->mCamera != 0) {
-        c->mCamera->asBinder()->linkToDeath(c);
+        IInterface::asBinder(c->mCamera)->linkToDeath(c);
         c->mStatus = NO_ERROR;
         camera = c;
     } else {
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 04694cd..65a1a47 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -107,7 +107,7 @@
                                              /*out*/ c->mCamera);
     }
     if (status == OK && c->mCamera != 0) {
-        c->mCamera->asBinder()->linkToDeath(c);
+        IInterface::asBinder(c->mCamera)->linkToDeath(c);
         c->mStatus = NO_ERROR;
     } else {
         ALOGW("An error occurred while connecting to camera: %d", cameraId);
@@ -122,7 +122,7 @@
     ALOGV("%s: disconnect", __FUNCTION__);
     if (mCamera != 0) {
         mCamera->disconnect();
-        mCamera->asBinder()->unlinkToDeath(this);
+        IInterface::asBinder(mCamera)->unlinkToDeath(this);
         mCamera = 0;
     }
     ALOGV("%s: disconnect (done)", __FUNCTION__);
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index 25d632d..68969cf 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -488,6 +488,11 @@
     const char* supportedPreviewFormats =
           get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS);
 
+    if (supportedPreviewFormats == NULL) {
+        ALOGW("%s: No supported preview formats.", __FUNCTION__);
+        return;
+    }
+
     String8 fmtStr(supportedPreviewFormats);
     char* prevFmts = fmtStr.lockBuffer(fmtStr.size());
 
@@ -521,8 +526,12 @@
         !strcmp(format, PIXEL_FORMAT_RGBA8888) ?
             HAL_PIXEL_FORMAT_RGBA_8888 :    // RGB8888
         !strcmp(format, PIXEL_FORMAT_BAYER_RGGB) ?
-            HAL_PIXEL_FORMAT_RAW_SENSOR :   // Raw sensor data
+            HAL_PIXEL_FORMAT_RAW16 :   // Raw sensor data
         -1;
 }
 
+bool CameraParameters::isEmpty() const {
+    return mMap.isEmpty();
+}
+
 }; // namespace android
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index 8c6e1f7..9943be6 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -75,7 +75,7 @@
         ALOGV("setPreviewTarget");
         Parcel data, reply;
         data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
-        sp<IBinder> b(bufferProducer->asBinder());
+        sp<IBinder> b(IInterface::asBinder(bufferProducer));
         data.writeStrongBinder(b);
         remote()->transact(SET_PREVIEW_TARGET, data, &reply);
         return reply.readInt32();
@@ -98,7 +98,7 @@
         ALOGV("setPreviewCallbackTarget");
         Parcel data, reply;
         data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
-        sp<IBinder> b(callbackProducer->asBinder());
+        sp<IBinder> b(IInterface::asBinder(callbackProducer));
         data.writeStrongBinder(b);
         remote()->transact(SET_PREVIEW_CALLBACK_TARGET, data, &reply);
         return reply.readInt32();
@@ -147,7 +147,7 @@
         ALOGV("releaseRecordingFrame");
         Parcel data, reply;
         data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
-        data.writeStrongBinder(mem->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(mem));
         remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
     }
 
@@ -250,7 +250,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
-        data.writeStrongBinder(cameraClient->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(cameraClient));
         remote()->transact(CONNECT, data, &reply);
         return reply.readInt32();
     }
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index 205c8ba..179a341 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -58,7 +58,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
         data.writeInt32(msgType);
-        data.writeStrongBinder(imageData->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(imageData));
         if (metadata) {
             data.writeInt32(metadata->number_of_faces);
             data.write(metadata->faces, sizeof(camera_face_t) * metadata->number_of_faces);
@@ -74,7 +74,7 @@
         data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
         data.writeInt64(timestamp);
         data.writeInt32(msgType);
-        data.writeStrongBinder(imageData->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(imageData));
         remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
diff --git a/camera/ICameraRecordingProxy.cpp b/camera/ICameraRecordingProxy.cpp
index 7223b6d..3dc0ffb 100644
--- a/camera/ICameraRecordingProxy.cpp
+++ b/camera/ICameraRecordingProxy.cpp
@@ -45,7 +45,7 @@
         ALOGV("startRecording");
         Parcel data, reply;
         data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
-        data.writeStrongBinder(listener->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(listener));
         remote()->transact(START_RECORDING, data, &reply);
         return reply.readInt32();
     }
@@ -63,7 +63,7 @@
         ALOGV("releaseRecordingFrame");
         Parcel data, reply;
         data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
-        data.writeStrongBinder(mem->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(mem));
         remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
     }
 };
diff --git a/camera/ICameraRecordingProxyListener.cpp b/camera/ICameraRecordingProxyListener.cpp
index cb17f19..cf848fc 100644
--- a/camera/ICameraRecordingProxyListener.cpp
+++ b/camera/ICameraRecordingProxyListener.cpp
@@ -42,7 +42,7 @@
         data.writeInterfaceToken(ICameraRecordingProxyListener::getInterfaceDescriptor());
         data.writeInt64(timestamp);
         data.writeInt32(msgType);
-        data.writeStrongBinder(imageData->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(imageData));
         remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 5485205..a75cb48 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -172,7 +172,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(cameraClient->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(cameraClient));
         data.writeInt32(cameraId);
         data.writeString16(clientPackageName);
         data.writeInt32(clientUid);
@@ -194,7 +194,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(cameraClient->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(cameraClient));
         data.writeInt32(cameraId);
         data.writeInt32(halVersion);
         data.writeString16(clientPackageName);
@@ -209,6 +209,20 @@
         return status;
     }
 
+    virtual status_t setTorchMode(const String16& cameraId, bool enabled,
+            const sp<IBinder>& clientBinder)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+        data.writeString16(cameraId);
+        data.writeInt32(enabled ? 1 : 0);
+        data.writeStrongBinder(clientBinder);
+        remote()->transact(BnCameraService::SET_TORCH_MODE, data, &reply);
+
+        if (readExceptionCode(reply)) return -EPROTO;
+        return reply.readInt32();
+    }
+
     // connect to camera service (pro client)
     virtual status_t connectPro(const sp<IProCameraCallbacks>& cameraCb, int cameraId,
                                 const String16 &clientPackageName, int clientUid,
@@ -217,7 +231,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(cameraCb->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(cameraCb));
         data.writeInt32(cameraId);
         data.writeString16(clientPackageName);
         data.writeInt32(clientUid);
@@ -242,7 +256,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(cameraCb->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(cameraCb));
         data.writeInt32(cameraId);
         data.writeString16(clientPackageName);
         data.writeInt32(clientUid);
@@ -260,7 +274,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(listener->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(listener));
         remote()->transact(BnCameraService::ADD_LISTENER, data, &reply);
 
         if (readExceptionCode(reply)) return -EPROTO;
@@ -271,7 +285,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
-        data.writeStrongBinder(listener->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(listener));
         remote()->transact(BnCameraService::REMOVE_LISTENER, data, &reply);
 
         if (readExceptionCode(reply)) return -EPROTO;
@@ -384,7 +398,7 @@
             reply->writeInt32(status);
             if (camera != NULL) {
                 reply->writeInt32(1);
-                reply->writeStrongBinder(camera->asBinder());
+                reply->writeStrongBinder(IInterface::asBinder(camera));
             } else {
                 reply->writeInt32(0);
             }
@@ -404,7 +418,7 @@
             reply->writeInt32(status);
             if (camera != NULL) {
                 reply->writeInt32(1);
-                reply->writeStrongBinder(camera->asBinder());
+                reply->writeStrongBinder(IInterface::asBinder(camera));
             } else {
                 reply->writeInt32(0);
             }
@@ -424,7 +438,7 @@
             reply->writeInt32(status);
             if (camera != NULL) {
                 reply->writeInt32(1);
-                reply->writeStrongBinder(camera->asBinder());
+                reply->writeStrongBinder(IInterface::asBinder(camera));
             } else {
                 reply->writeInt32(0);
             }
@@ -484,12 +498,22 @@
             reply->writeInt32(status);
             if (camera != NULL) {
                 reply->writeInt32(1);
-                reply->writeStrongBinder(camera->asBinder());
+                reply->writeStrongBinder(IInterface::asBinder(camera));
             } else {
                 reply->writeInt32(0);
             }
             return NO_ERROR;
         } break;
+        case SET_TORCH_MODE: {
+            CHECK_INTERFACE(ICameraService, data, reply);
+            String16 cameraId = data.readString16();
+            bool enabled = data.readInt32() != 0 ? true : false;
+            const sp<IBinder> clientBinder = data.readStrongBinder();
+            status_t status = setTorchMode(cameraId, enabled, clientBinder);
+            reply->writeNoException();
+            reply->writeInt32(status);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/camera/ICameraServiceListener.cpp b/camera/ICameraServiceListener.cpp
index b2f1729..90a8bc2 100644
--- a/camera/ICameraServiceListener.cpp
+++ b/camera/ICameraServiceListener.cpp
@@ -29,6 +29,7 @@
 namespace {
     enum {
         STATUS_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
+        TORCH_STATUS_CHANGED,
     };
 }; // namespace anonymous
 
@@ -54,8 +55,21 @@
                            data,
                            &reply,
                            IBinder::FLAG_ONEWAY);
+    }
 
-        reply.readExceptionCode();
+    virtual void onTorchStatusChanged(TorchStatus status, const String16 &cameraId)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                              ICameraServiceListener::getInterfaceDescriptor());
+
+        data.writeInt32(static_cast<int32_t>(status));
+        data.writeString16(cameraId);
+
+        remote()->transact(TORCH_STATUS_CHANGED,
+                           data,
+                           &reply,
+                           IBinder::FLAG_ONEWAY);
     }
 };
 
@@ -75,7 +89,16 @@
             int32_t cameraId = data.readInt32();
 
             onStatusChanged(status, cameraId);
-            reply->writeNoException();
+
+            return NO_ERROR;
+        } break;
+        case TORCH_STATUS_CHANGED: {
+            CHECK_INTERFACE(ICameraServiceListener, data, reply);
+
+            TorchStatus status = static_cast<TorchStatus>(data.readInt32());
+            String16 cameraId = data.readString16();
+
+            onTorchStatusChanged(status, cameraId);
 
             return NO_ERROR;
         } break;
diff --git a/camera/IProCameraUser.cpp b/camera/IProCameraUser.cpp
index 8f22124..9bd7597 100644
--- a/camera/IProCameraUser.cpp
+++ b/camera/IProCameraUser.cpp
@@ -65,7 +65,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
-        data.writeStrongBinder(cameraClient->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(cameraClient));
         remote()->transact(CONNECT, data, &reply);
         return reply.readInt32();
     }
@@ -150,7 +150,7 @@
         data.writeInt32(height);
         data.writeInt32(format);
 
-        sp<IBinder> b(bufferProducer->asBinder());
+        sp<IBinder> b(IInterface::asBinder(bufferProducer));
         data.writeStrongBinder(b);
 
         remote()->transact(CREATE_STREAM, data, &reply);
diff --git a/camera/camera2/CaptureRequest.cpp b/camera/camera2/CaptureRequest.cpp
index 57e5319..66d6913 100644
--- a/camera/camera2/CaptureRequest.cpp
+++ b/camera/camera2/CaptureRequest.cpp
@@ -63,9 +63,9 @@
         }
 
         // Surface.writeToParcel
-        String16 name = parcel->readString16();
-        ALOGV("%s: Read surface name = %s",
-              __FUNCTION__, String8(name).string());
+        const char16_t* name = parcel->readString16Inplace(&len);
+        ALOGV("%s: Read surface name = %s", __FUNCTION__,
+            name != NULL ? String8(name).string() : "<null>");
         sp<IBinder> binder(parcel->readStrongBinder());
         ALOGV("%s: Read surface binder = %p",
               __FUNCTION__, binder.get());
@@ -106,7 +106,7 @@
 
         sp<IBinder> binder;
         if (surface != 0) {
-            binder = surface->getIGraphicBufferProducer()->asBinder();
+            binder = IInterface::asBinder(surface->getIGraphicBufferProducer());
         }
 
         // not sure if readParcelableArray does this, hard to tell from source
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index ff4a0c2..89c6fb7 100644
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ b/camera/camera2/ICameraDeviceUser.cpp
@@ -26,6 +26,7 @@
 #include <gui/Surface.h>
 #include <camera/CameraMetadata.h>
 #include <camera/camera2/CaptureRequest.h>
+#include <camera/camera2/OutputConfiguration.h>
 
 namespace android {
 
@@ -107,7 +108,7 @@
             }
         }
 
-	if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+	if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
             res = FAILED_TRANSACTION;
         }
         return res;
@@ -147,7 +148,7 @@
                 resFrameNumber = reply.readInt64(lastFrameNumber);
             }
         }
-        if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+        if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
             res = FAILED_TRANSACTION;
         }
         return res;
@@ -167,7 +168,7 @@
         status_t resFrameNumber = BAD_VALUE;
         if (reply.readInt32() != 0) {
             if (lastFrameNumber != NULL) {
-                res = reply.readInt64(lastFrameNumber);
+                resFrameNumber = reply.readInt64(lastFrameNumber);
             }
         }
         if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
@@ -208,20 +209,16 @@
         return reply.readInt32();
     }
 
-    virtual status_t createStream(int width, int height, int format,
-                          const sp<IGraphicBufferProducer>& bufferProducer)
+    virtual status_t createStream(const OutputConfiguration& outputConfiguration)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
-        data.writeInt32(width);
-        data.writeInt32(height);
-        data.writeInt32(format);
-
-        data.writeInt32(1); // marker that bufferProducer is not null
-        data.writeString16(String16("unknown_name")); // name of surface
-        sp<IBinder> b(bufferProducer->asBinder());
-        data.writeStrongBinder(b);
-
+        if (outputConfiguration.getGraphicBufferProducer() != NULL) {
+            data.writeInt32(1); // marker that OutputConfiguration is not null. Mimic aidl behavior
+            outputConfiguration.writeToParcel(data);
+        } else {
+            data.writeInt32(0);
+        }
         remote()->transact(CREATE_STREAM, data, &reply);
 
         reply.readExceptionCode();
@@ -296,7 +293,7 @@
         status_t resFrameNumber = BAD_VALUE;
         if (reply.readInt32() != 0) {
             if (lastFrameNumber != NULL) {
-                res = reply.readInt64(lastFrameNumber);
+                resFrameNumber = reply.readInt64(lastFrameNumber);
             }
         }
         if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
@@ -396,31 +393,15 @@
         } break;
         case CREATE_STREAM: {
             CHECK_INTERFACE(ICameraDeviceUser, data, reply);
-            int width, height, format;
 
-            width = data.readInt32();
-            ALOGV("%s: CREATE_STREAM: width = %d", __FUNCTION__, width);
-            height = data.readInt32();
-            ALOGV("%s: CREATE_STREAM: height = %d", __FUNCTION__, height);
-            format = data.readInt32();
-            ALOGV("%s: CREATE_STREAM: format = %d", __FUNCTION__, format);
-
-            sp<IGraphicBufferProducer> bp;
+            status_t ret = BAD_VALUE;
             if (data.readInt32() != 0) {
-                String16 name = readMaybeEmptyString16(data);
-                bp = interface_cast<IGraphicBufferProducer>(
-                        data.readStrongBinder());
-
-                ALOGV("%s: CREATE_STREAM: bp = %p, name = %s", __FUNCTION__,
-                      bp.get(), String8(name).string());
+                OutputConfiguration outputConfiguration(data);
+                ret = createStream(outputConfiguration);
             } else {
-                ALOGV("%s: CREATE_STREAM: bp = unset, name = unset",
-                      __FUNCTION__);
+                ALOGE("%s: cannot take an empty OutputConfiguration", __FUNCTION__);
             }
 
-            status_t ret;
-            ret = createStream(width, height, format, bp);
-
             reply->writeNoException();
             ALOGV("%s: CREATE_STREAM: write noException", __FUNCTION__);
             reply->writeInt32(ret);
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
new file mode 100644
index 0000000..24acaa0
--- /dev/null
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -0,0 +1,79 @@
+/*
+**
+** 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 "OutputConfiguration"
+#include <utils/Log.h>
+
+#include <camera/camera2/OutputConfiguration.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+
+const int OutputConfiguration::INVALID_ROTATION = -1;
+
+// Read empty strings without printing a false error message.
+String16 OutputConfiguration::readMaybeEmptyString16(const Parcel& parcel) {
+    size_t len;
+    const char16_t* str = parcel.readString16Inplace(&len);
+    if (str != NULL) {
+        return String16(str, len);
+    } else {
+        return String16();
+    }
+}
+
+sp<IGraphicBufferProducer> OutputConfiguration::getGraphicBufferProducer() const {
+    return mGbp;
+}
+
+int OutputConfiguration::getRotation() const {
+    return mRotation;
+}
+
+OutputConfiguration::OutputConfiguration(const Parcel& parcel) {
+    status_t err;
+    int rotation = 0;
+    if ((err = parcel.readInt32(&rotation)) != OK) {
+        ALOGE("%s: Failed to read rotation from parcel", __FUNCTION__);
+        mGbp = NULL;
+        mRotation = INVALID_ROTATION;
+        return;
+    }
+
+    String16 name = readMaybeEmptyString16(parcel);
+    const sp<IGraphicBufferProducer>& gbp =
+            interface_cast<IGraphicBufferProducer>(parcel.readStrongBinder());
+    mGbp = gbp;
+    mRotation = rotation;
+
+    ALOGV("%s: OutputConfiguration: bp = %p, name = %s", __FUNCTION__,
+          gbp.get(), String8(name).string());
+}
+
+status_t OutputConfiguration::writeToParcel(Parcel& parcel) const {
+
+    parcel.writeInt32(mRotation);
+    parcel.writeString16(String16("unknown_name")); // name of surface
+    sp<IBinder> b(IInterface::asBinder(mGbp));
+    parcel.writeStrongBinder(b);
+
+    return OK;
+}
+
+}; // namespace android
+
diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp
index 1f5867a..24b2327 100644
--- a/camera/tests/ProCameraTests.cpp
+++ b/camera/tests/ProCameraTests.cpp
@@ -89,6 +89,12 @@
         mCondition.broadcast();
     }
 
+    void onTorchStatusChanged(TorchStatus status, const String16& cameraId) {
+        dout << "On torch status changed: 0x" << std::hex
+             << (unsigned int) status << " cameraId " << cameraId.string()
+             << std::endl;
+    }
+
     status_t waitForStatusChange(Status& newStatus) {
         Mutex::Autolock al(mMutex);
 
@@ -469,7 +475,7 @@
         CMP_STR(NV16, YCbCr_422_SP);
         CMP_STR(NV21, YCrCb_420_SP);
         CMP_STR(YUY2, YCbCr_422_I);
-        CMP_STR(RAW,  RAW_SENSOR);
+        CMP_STR(RAW,  RAW16);
         CMP_STR(RGBA, RGBA_8888);
 
         std::cerr << "Unknown format string " << str << std::endl;
diff --git a/cmds/screenrecord/FrameOutput.cpp b/cmds/screenrecord/FrameOutput.cpp
index 03e0062..bef74f5 100644
--- a/cmds/screenrecord/FrameOutput.cpp
+++ b/cmds/screenrecord/FrameOutput.cpp
@@ -206,7 +206,7 @@
 }
 
 // Callback; executes on arbitrary thread.
-void FrameOutput::onFrameAvailable() {
+void FrameOutput::onFrameAvailable(const BufferItem& /* item */) {
     Mutex::Autolock _l(mMutex);
     mFrameAvailable = true;
     mEventCond.signal();
diff --git a/cmds/screenrecord/FrameOutput.h b/cmds/screenrecord/FrameOutput.h
index c49ec3b..4c0c3be 100644
--- a/cmds/screenrecord/FrameOutput.h
+++ b/cmds/screenrecord/FrameOutput.h
@@ -62,7 +62,7 @@
     }
 
     // (overrides GLConsumer::FrameAvailableListener method)
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
 
     // Reduces RGBA to RGB, in place.
     static void reduceRgbaToRgb(uint8_t* buf, unsigned int pixelCount);
diff --git a/cmds/screenrecord/Overlay.cpp b/cmds/screenrecord/Overlay.cpp
index 7fef53d..c659170 100644
--- a/cmds/screenrecord/Overlay.cpp
+++ b/cmds/screenrecord/Overlay.cpp
@@ -274,7 +274,7 @@
 }
 
 // Callback; executes on arbitrary thread.
-void Overlay::onFrameAvailable() {
+void Overlay::onFrameAvailable(const BufferItem& /* item */) {
     ALOGV("Overlay::onFrameAvailable");
     Mutex::Autolock _l(mMutex);
     mFrameAvailable = true;
diff --git a/cmds/screenrecord/Overlay.h b/cmds/screenrecord/Overlay.h
index b1b5c29..ee3444d 100644
--- a/cmds/screenrecord/Overlay.h
+++ b/cmds/screenrecord/Overlay.h
@@ -78,7 +78,7 @@
             const Program& texRender, TextRenderer& textRenderer);
 
     // (overrides GLConsumer::FrameAvailableListener method)
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
 
     // (overrides Thread method)
     virtual bool threadLoop();
diff --git a/cmds/screenrecord/TextRenderer.cpp b/cmds/screenrecord/TextRenderer.cpp
index 6a9176b..01f73e0 100644
--- a/cmds/screenrecord/TextRenderer.cpp
+++ b/cmds/screenrecord/TextRenderer.cpp
@@ -21,6 +21,8 @@
 #include "TextRenderer.h"
 
 #include <assert.h>
+#include <malloc.h>
+#include <string.h>
 
 namespace android {
 #include "FontBitmap.h"
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 02df1d2..36a7e73 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -23,7 +23,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <sys/wait.h>
+
 #include <termios.h>
 #include <unistd.h>
 
@@ -637,7 +640,13 @@
         case FORMAT_MP4: {
             // Configure muxer.  We have to wait for the CSD blob from the encoder
             // before we can start it.
-            muxer = new MediaMuxer(fileName, MediaMuxer::OUTPUT_FORMAT_MPEG_4);
+            int fd = open(fileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+            if (fd < 0) {
+                fprintf(stderr, "ERROR: couldn't open file\n");
+                abort();
+            }
+            muxer = new MediaMuxer(fd, MediaMuxer::OUTPUT_FORMAT_MPEG_4);
+            close(fd);
             if (gRotate) {
                 muxer->setOrientationHint(90);  // TODO: does this do anything?
             }
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 78c89bb..0e3bc68 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -169,8 +169,6 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_NDK_STL_VARIANT := stlport_static
-
 LOCAL_SRC_FILES:= \
 	filters/argbtorgba.rs \
 	filters/nightvision.rs \
@@ -178,12 +176,18 @@
 	mediafilter.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
-	libstagefright liblog libutils libbinder libstagefright_foundation \
-	libmedia libgui libcutils libui
+	libstagefright \
+	liblog \
+	libutils \
+	libbinder \
+	libstagefright_foundation \
+	libmedia \
+	libgui \
+	libcutils \
+	libui \
+	libRScpp \
 
 LOCAL_C_INCLUDES:= \
-	$(TOP)/bionic \
-	$(TOP)/external/stlport/stlport \
 	$(TOP)/frameworks/av/media/libstagefright \
 	$(TOP)/frameworks/native/include/media/openmax \
 	$(TOP)/frameworks/rs/cpp \
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index 1b2f792..ac1a547 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -59,14 +59,14 @@
     return err;
 }
 status_t SimplePlayer::setDataSource(const char *path) {
-    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
     msg->setString("path", path);
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
 
 status_t SimplePlayer::setSurface(const sp<IGraphicBufferProducer> &bufferProducer) {
-    sp<AMessage> msg = new AMessage(kWhatSetSurface, id());
+    sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
 
     sp<Surface> surface;
     if (bufferProducer != NULL) {
@@ -81,25 +81,25 @@
 }
 
 status_t SimplePlayer::prepare() {
-    sp<AMessage> msg = new AMessage(kWhatPrepare, id());
+    sp<AMessage> msg = new AMessage(kWhatPrepare, this);
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
 
 status_t SimplePlayer::start() {
-    sp<AMessage> msg = new AMessage(kWhatStart, id());
+    sp<AMessage> msg = new AMessage(kWhatStart, this);
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
 
 status_t SimplePlayer::stop() {
-    sp<AMessage> msg = new AMessage(kWhatStop, id());
+    sp<AMessage> msg = new AMessage(kWhatStop, this);
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
 
 status_t SimplePlayer::reset() {
-    sp<AMessage> msg = new AMessage(kWhatReset, id());
+    sp<AMessage> msg = new AMessage(kWhatReset, this);
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
@@ -116,7 +116,7 @@
                 mState = UNPREPARED;
             }
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             sp<AMessage> response = new AMessage;
@@ -139,7 +139,7 @@
                 err = OK;
             }
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             sp<AMessage> response = new AMessage;
@@ -161,7 +161,7 @@
                 }
             }
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             sp<AMessage> response = new AMessage;
@@ -194,7 +194,7 @@
                 }
             }
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             sp<AMessage> response = new AMessage;
@@ -217,7 +217,7 @@
                 }
             }
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             sp<AMessage> response = new AMessage;
@@ -240,7 +240,7 @@
                 mState = UNINITIALIZED;
             }
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             sp<AMessage> response = new AMessage;
@@ -332,7 +332,7 @@
 
         size_t j = 0;
         sp<ABuffer> buffer;
-        while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) {
+        while (format->findBuffer(AStringPrintf("csd-%d", j).c_str(), &buffer)) {
             state->mCSD.push_back(buffer);
 
             ++j;
@@ -382,7 +382,7 @@
 
     mStartTimeRealUs = -1ll;
 
-    sp<AMessage> msg = new AMessage(kWhatDoMoreStuff, id());
+    sp<AMessage> msg = new AMessage(kWhatDoMoreStuff, this);
     msg->setInt32("generation", ++mDoMoreStuffGeneration);
     msg->post();
 
diff --git a/cmds/stagefright/SineSource.h b/cmds/stagefright/SineSource.h
index 76ab669..be05661 100644
--- a/cmds/stagefright/SineSource.h
+++ b/cmds/stagefright/SineSource.h
@@ -3,10 +3,11 @@
 #define SINE_SOURCE_H_
 
 #include <media/stagefright/MediaSource.h>
+#include <utils/Compat.h>
 
 namespace android {
 
-struct MediaBufferGroup;
+class MediaBufferGroup;
 
 struct SineSource : public MediaSource {
     SineSource(int32_t sampleRate, int32_t numChannels);
@@ -24,7 +25,7 @@
 
 private:
     enum { kBufferSize = 8192 };
-    static const double kFrequency = 500.0;
+    static const CONSTEXPR double kFrequency = 500.0;
 
     bool mStarted;
     int32_t mSampleRate;
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index 96073f1..7b0de24 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 #include <binder/ProcessState.h>
 #include <media/mediarecorder.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -109,7 +113,12 @@
 
     if (fileOut != NULL) {
         // target file specified, write encoded AMR output
-        sp<AMRWriter> writer = new AMRWriter(fileOut);
+        int fd = open(fileOut, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+        if (fd < 0) {
+            return 1;
+        }
+        sp<AMRWriter> writer = new AMRWriter(fd);
+        close(fd);
         writer->addSource(encoder);
         writer->start();
         sleep(duration);
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index f4a33e8..461b56c 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -17,6 +17,9 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "muxer"
 #include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <utils/Log.h>
 
 #include <binder/ProcessState.h>
@@ -72,8 +75,15 @@
     ALOGV("input file %s, output file %s", path, outputFileName);
     ALOGV("useAudio %d, useVideo %d", useAudio, useVideo);
 
-    sp<MediaMuxer> muxer = new MediaMuxer(outputFileName,
+    int fd = open(outputFileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+
+    if (fd < 0) {
+        ALOGE("couldn't open file");
+        return fd;
+    }
+    sp<MediaMuxer> muxer = new MediaMuxer(fd,
                                           MediaMuxer::OUTPUT_FORMAT_MPEG_4);
+    close(fd);
 
     size_t trackCount = extractor->countTracks();
     // Map the extractor's track index to the muxer's track index.
diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp
index 9f547c7..2ad40bd 100644
--- a/cmds/stagefright/recordvideo.cpp
+++ b/cmds/stagefright/recordvideo.cpp
@@ -17,6 +17,10 @@
 #include "SineSource.h"
 
 #include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 #include <binder/ProcessState.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/AudioPlayer.h>
@@ -300,7 +304,13 @@
                 client.interface(), enc_meta, true /* createEncoder */, source,
                 0, preferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0);
 
-    sp<MPEG4Writer> writer = new MPEG4Writer(fileName);
+    int fd = open(fileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    if (fd < 0) {
+        fprintf(stderr, "couldn't open file");
+        return 1;
+    }
+    sp<MPEG4Writer> writer = new MPEG4Writer(fd);
+    close(fd);
     writer->addSource(encoder);
     int64_t start = systemTime();
     CHECK_EQ((status_t)OK, writer->start());
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 0f729a3..172dc36 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -72,7 +72,7 @@
     }
 
     void startAsync() {
-        (new AMessage(kWhatStart, id()))->post();
+        (new AMessage(kWhatStart, this))->post();
     }
 
 protected:
@@ -100,7 +100,7 @@
         if (ctrlc) {
             printf("\n");
             printStatistics();
-            (new AMessage(kWhatStop, id()))->post();
+            (new AMessage(kWhatStop, this))->post();
             ctrlc = false;
         }
         switch (msg->what()) {
@@ -149,7 +149,7 @@
                 mDecodeLooper->registerHandler(mCodec);
 
                 mCodec->setNotificationMessage(
-                        new AMessage(kWhatCodecNotify, id()));
+                        new AMessage(kWhatCodecNotify, this));
 
                 sp<AMessage> format = makeFormat(mSource->getFormat());
 
@@ -168,7 +168,7 @@
                 mFinalResult = OK;
                 mSeekState = SEEK_NONE;
 
-                // (new AMessage(kWhatSeek, id()))->post(5000000ll);
+                // (new AMessage(kWhatSeek, this))->post(5000000ll);
                 break;
             }
 
@@ -225,12 +225,12 @@
                     printf((what == CodecBase::kWhatEOS) ? "$\n" : "E\n");
 
                     printStatistics();
-                    (new AMessage(kWhatStop, id()))->post();
+                    (new AMessage(kWhatStop, this))->post();
                 } else if (what == CodecBase::kWhatFlushCompleted) {
                     mSeekState = SEEK_FLUSH_COMPLETED;
                     mCodec->signalResume();
 
-                    (new AMessage(kWhatSeek, id()))->post(5000000ll);
+                    (new AMessage(kWhatSeek, this))->post(5000000ll);
                 } else if (what == CodecBase::kWhatOutputFormatChanged) {
                 } else if (what == CodecBase::kWhatShutdownCompleted) {
                     mDecodeLooper->unregisterHandler(mCodec->id());
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 81edcb4..318b56d 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -19,6 +19,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "stagefright"
@@ -506,8 +508,13 @@
     sp<MPEG4Writer> writer =
         new MPEG4Writer(gWriteMP4Filename.string());
 #else
+    int fd = open(gWriteMP4Filename.string(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+    if (fd < 0) {
+        fprintf(stderr, "couldn't open file");
+        return;
+    }
     sp<MPEG2TSWriter> writer =
-        new MPEG2TSWriter(gWriteMP4Filename.string());
+        new MPEG2TSWriter(fd);
 #endif
 
     // at most one minute.
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 36cb612..3f62ed7 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -148,8 +148,7 @@
 
     data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
     data.writeInt32(uniqueId);
-    data.writeStrongBinder(
-        drmServiceListener != NULL ? drmServiceListener->asBinder() : NULL);
+    data.writeStrongBinder(IInterface::asBinder(drmServiceListener));
     remote()->transact(SET_DRM_SERVICE_LISTENER, data, &reply);
     return reply.readInt32();
 }
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index 2d2c90e..9457bb6 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -346,7 +346,7 @@
 DrmManagerClientImpl::DeathNotifier::~DeathNotifier() {
     Mutex::Autolock lock(sMutex);
     if (NULL != sDrmManagerService.get()) {
-        sDrmManagerService->asBinder()->unlinkToDeath(this);
+        IInterface::asBinder(sDrmManagerService)->unlinkToDeath(this);
     }
 }
 
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
index 48b0afe..933464f 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
@@ -58,8 +58,7 @@
     $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/common \
     $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/converter \
     $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/decoder \
-    $(LOCAL_PATH)/include \
-    external/openssl/include
+    $(LOCAL_PATH)/include
 
 LOCAL_MODULE_RELATIVE_PATH := drm
 
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
index 6c5d3cf..3b4c8b4 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
@@ -20,9 +20,6 @@
 LOCAL_SRC_FILES := \
     FwdLockGlue.c
 
-LOCAL_C_INCLUDES := \
-    external/openssl/include
-
 LOCAL_SHARED_LIBRARIES := libcrypto
 
 LOCAL_MODULE := libfwdlock-common
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
index 8f08c88..2f51f0c 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
@@ -21,8 +21,7 @@
     FwdLockConv.c
 
 LOCAL_C_INCLUDES := \
-    frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common \
-    external/openssl/include
+    frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common
 
 LOCAL_SHARED_LIBRARIES := libcrypto
 
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
index 7b493c3..3399ae5 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
@@ -21,8 +21,7 @@
     FwdLockFile.c
 
 LOCAL_C_INCLUDES := \
-    frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common \
-    external/openssl/include
+    frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common
 
 LOCAL_SHARED_LIBRARIES := libcrypto
 
diff --git a/drm/mediadrm/plugins/clearkey/Android.mk b/drm/mediadrm/plugins/clearkey/Android.mk
index 22a85b4..2efdcf5 100644
--- a/drm/mediadrm/plugins/clearkey/Android.mk
+++ b/drm/mediadrm/plugins/clearkey/Android.mk
@@ -31,9 +31,7 @@
     Utils.cpp \
 
 LOCAL_C_INCLUDES := \
-    bionic \
     external/jsmn \
-    external/openssl/include \
     frameworks/av/drm/mediadrm/plugins/clearkey \
     frameworks/av/include \
     frameworks/native/include \
diff --git a/drm/mediadrm/plugins/clearkey/tests/Android.mk b/drm/mediadrm/plugins/clearkey/tests/Android.mk
index ac5bb21..392f218 100644
--- a/drm/mediadrm/plugins/clearkey/tests/Android.mk
+++ b/drm/mediadrm/plugins/clearkey/tests/Android.mk
@@ -28,25 +28,16 @@
     JsonWebKeyUnittest.cpp \
 
 LOCAL_C_INCLUDES := \
-    bionic \
-    external/gtest/include \
     external/jsmn \
-    external/openssl/include \
-    external/stlport/stlport \
     frameworks/av/drm/mediadrm/plugins/clearkey \
     frameworks/av/include \
     frameworks/native/include \
 
-LOCAL_STATIC_LIBRARIES := \
-    libgtest \
-    libgtest_main \
-
 LOCAL_SHARED_LIBRARIES := \
     libcrypto \
     libdrmclearkeyplugin \
     liblog \
     libstagefright_foundation \
-    libstlport \
     libutils \
 
 include $(BUILD_NATIVE_TEST)
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index c6074fc..ba33ffe 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -108,6 +108,9 @@
      */
     void getSupportedPreviewFormats(Vector<int>& formats) const;
 
+    // Returns true if no keys are present
+    bool isEmpty() const;
+
     // Parameter keys to communicate between camera application and driver.
     // The access (read/write, read only, or write only) is viewed from the
     // perspective of applications, not driver.
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index f7f06bb..194a646 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -53,6 +53,7 @@
         GET_LEGACY_PARAMETERS,
         SUPPORTS_CAMERA_API,
         CONNECT_LEGACY,
+        SET_TORCH_MODE,
     };
 
     enum {
@@ -142,6 +143,21 @@
             int clientUid,
             /*out*/
             sp<ICamera>& device) = 0;
+
+    /**
+     * Turn on or off a camera's torch mode. Torch mode will be turned off by
+     * camera service if the lastest client binder that turns it on dies.
+     *
+     * return values:
+     * 0:       on a successful operation.
+     * -ENOSYS: the camera device doesn't support this operation. It it returned
+     *          if and only if android.flash.into.available is false.
+     * -EBUSY:  the camera device is opened.
+     * -EINVAL: camera_id is invalid or clientBinder is NULL when enabling a
+     *          torch mode.
+     */
+    virtual status_t setTorchMode(const String16& cameraId, bool enabled,
+            const sp<IBinder>& clientBinder) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/camera/ICameraServiceListener.h b/include/camera/ICameraServiceListener.h
index 0a0e43a..709ff31 100644
--- a/include/camera/ICameraServiceListener.h
+++ b/include/camera/ICameraServiceListener.h
@@ -66,9 +66,35 @@
         STATUS_UNKNOWN          = 0xFFFFFFFF,
     };
 
+    /**
+     * The torch mode status of a camera.
+     *
+     * Initial status will be transmitted with onTorchStatusChanged immediately
+     * after this listener is added to the service listener list.
+     *
+     * The enums should be set to values matching
+     * include/hardware/camera_common.h
+     */
+    enum TorchStatus {
+        // The camera's torch mode has become not available to use via
+        // setTorchMode().
+        TORCH_STATUS_NOT_AVAILABLE  = TORCH_MODE_STATUS_NOT_AVAILABLE,
+        // The camera's torch mode is off and available to be turned on via
+        // setTorchMode().
+        TORCH_STATUS_AVAILABLE_OFF  = TORCH_MODE_STATUS_AVAILABLE_OFF,
+        // The camera's torch mode is on and available to be turned off via
+        // setTorchMode().
+        TORCH_STATUS_AVAILABLE_ON   = TORCH_MODE_STATUS_AVAILABLE_ON,
+
+        // Use to initialize variables only
+        TORCH_STATUS_UNKNOWN        = 0xFFFFFFFF,
+    };
+
     DECLARE_META_INTERFACE(CameraServiceListener);
 
     virtual void onStatusChanged(Status status, int32_t cameraId) = 0;
+
+    virtual void onTorchStatusChanged(TorchStatus status, const String16& cameraId) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/camera/ProCamera.h b/include/camera/ProCamera.h
index 83a3028..e9b687a 100644
--- a/include/camera/ProCamera.h
+++ b/include/camera/ProCamera.h
@@ -265,7 +265,7 @@
         }
 
     protected:
-        virtual void onFrameAvailable() {
+        virtual void onFrameAvailable(const BufferItem& /* item */) {
             sp<ProCamera> c = mCamera.promote();
             if (c.get() != NULL) {
                 c->onFrameAvailable(mStreamId);
diff --git a/include/camera/camera2/ICameraDeviceUser.h b/include/camera/camera2/ICameraDeviceUser.h
index 35488bb..e9f1f5a 100644
--- a/include/camera/camera2/ICameraDeviceUser.h
+++ b/include/camera/camera2/ICameraDeviceUser.h
@@ -27,9 +27,9 @@
 
 class ICameraDeviceUserClient;
 class IGraphicBufferProducer;
-class Surface;
 class CaptureRequest;
 class CameraMetadata;
+class OutputConfiguration;
 
 enum {
     NO_IN_FLIGHT_REPEATING_FRAMES = -1,
@@ -100,9 +100,8 @@
     virtual status_t        endConfigure() = 0;
 
     virtual status_t        deleteStream(int streamId) = 0;
-    virtual status_t        createStream(
-            int width, int height, int format,
-            const sp<IGraphicBufferProducer>& bufferProducer) = 0;
+
+    virtual status_t        createStream(const OutputConfiguration& outputConfiguration) = 0;
 
     // Create a request object from a template.
     virtual status_t        createDefaultRequest(int templateId,
diff --git a/include/camera/camera2/OutputConfiguration.h b/include/camera/camera2/OutputConfiguration.h
new file mode 100644
index 0000000..e6b679f
--- /dev/null
+++ b/include/camera/camera2/OutputConfiguration.h
@@ -0,0 +1,51 @@
+/*
+ * 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_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H
+#define ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H
+
+#include <utils/RefBase.h>
+#include <gui/IGraphicBufferProducer.h>
+
+namespace android {
+
+class Surface;
+
+class OutputConfiguration : public virtual RefBase {
+public:
+
+    static const int INVALID_ROTATION;
+    sp<IGraphicBufferProducer> getGraphicBufferProducer() const;
+    int                        getRotation() const;
+
+    /**
+     * Keep impl up-to-date with OutputConfiguration.java in frameworks/base
+     */
+    status_t                   writeToParcel(Parcel& parcel) const;
+    // getGraphicBufferProducer will be NULL if error occurred
+    // getRotation will be INVALID_ROTATION if error occurred
+    OutputConfiguration(const Parcel& parcel);
+
+private:
+    sp<IGraphicBufferProducer> mGbp;
+    int                        mRotation;
+
+    // helper function
+    static String16 readMaybeEmptyString16(const Parcel& parcel);
+};
+}; // namespace android
+
+#endif
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h
new file mode 100644
index 0000000..a755e1e
--- /dev/null
+++ b/include/media/AudioPolicy.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 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_AUDIO_POLICY_H
+#define ANDROID_AUDIO_POLICY_H
+
+#include <system/audio.h>
+#include <system/audio_policy.h>
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+// Keep in sync with AudioMix.java, AudioMixingRule.java, AudioPolicyConfig.java
+#define RULE_EXCLUSION_MASK 0x8000
+#define RULE_MATCH_ATTRIBUTE_USAGE 0x1
+#define RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET (0x1 << 1)
+#define RULE_EXCLUDE_ATTRIBUTE_USAGE (RULE_EXCLUSION_MASK|RULE_MATCH_ATTRIBUTE_USAGE)
+#define RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET \
+    (RULE_EXCLUSION_MASK|RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET)
+
+#define MIX_TYPE_INVALID -1
+#define MIX_TYPE_PLAYERS 0
+#define MIX_TYPE_RECORDERS 1
+
+#define ROUTE_FLAG_RENDER 0x1
+#define ROUTE_FLAG_LOOP_BACK (0x1 << 1)
+
+#define MAX_MIXES_PER_POLICY 10
+#define MAX_CRITERIA_PER_MIX 20
+
+class AttributeMatchCriterion {
+public:
+    AttributeMatchCriterion() {}
+    AttributeMatchCriterion(audio_usage_t usage, audio_source_t source, uint32_t rule);
+
+    status_t readFromParcel(Parcel *parcel);
+    status_t writeToParcel(Parcel *parcel) const;
+
+    union {
+        audio_usage_t   mUsage;
+        audio_source_t  mSource;
+    } mAttr;
+    uint32_t        mRule;
+};
+
+class AudioMix {
+public:
+    AudioMix() {}
+    AudioMix(Vector<AttributeMatchCriterion> criteria, uint32_t mixType, audio_config_t format,
+             uint32_t routeFlags, String8 registrationId) :
+        mCriteria(criteria), mMixType(mixType), mFormat(format),
+        mRouteFlags(routeFlags), mRegistrationId(registrationId) {}
+
+    status_t readFromParcel(Parcel *parcel);
+    status_t writeToParcel(Parcel *parcel) const;
+
+    Vector<AttributeMatchCriterion> mCriteria;
+    uint32_t        mMixType;
+    audio_config_t  mFormat;
+    uint32_t        mRouteFlags;
+    String8         mRegistrationId;
+};
+
+}; // namespace android
+
+#endif  // ANDROID_AUDIO_POLICY_H
diff --git a/include/media/AudioPolicyHelper.h b/include/media/AudioPolicyHelper.h
index f4afd45..79231be 100644
--- a/include/media/AudioPolicyHelper.h
+++ b/include/media/AudioPolicyHelper.h
@@ -18,7 +18,7 @@
 
 #include <system/audio.h>
 
-audio_stream_type_t audio_attributes_to_stream_type(const audio_attributes_t *attr)
+static audio_stream_type_t audio_attributes_to_stream_type(const audio_attributes_t *attr)
 {
     // flags to stream type mapping
     if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
@@ -61,4 +61,55 @@
     }
 }
 
+static void stream_type_to_audio_attributes(audio_stream_type_t streamType,
+                                     audio_attributes_t *attr) {
+    memset(attr, 0, sizeof(audio_attributes_t));
+
+    switch (streamType) {
+    case AUDIO_STREAM_DEFAULT:
+    case AUDIO_STREAM_MUSIC:
+        attr->content_type = AUDIO_CONTENT_TYPE_MUSIC;
+        attr->usage = AUDIO_USAGE_MEDIA;
+        break;
+    case AUDIO_STREAM_VOICE_CALL:
+        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
+        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION;
+        break;
+    case AUDIO_STREAM_ENFORCED_AUDIBLE:
+        attr->flags  |= AUDIO_FLAG_AUDIBILITY_ENFORCED;
+        // intended fall through, attributes in common with STREAM_SYSTEM
+    case AUDIO_STREAM_SYSTEM:
+        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+        attr->usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+        break;
+    case AUDIO_STREAM_RING:
+        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+        attr->usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+        break;
+    case AUDIO_STREAM_ALARM:
+        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+        attr->usage = AUDIO_USAGE_ALARM;
+        break;
+    case AUDIO_STREAM_NOTIFICATION:
+        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+        attr->usage = AUDIO_USAGE_NOTIFICATION;
+        break;
+    case AUDIO_STREAM_BLUETOOTH_SCO:
+        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
+        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION;
+        attr->flags |= AUDIO_FLAG_SCO;
+        break;
+    case AUDIO_STREAM_DTMF:
+        attr->content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+        attr->usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+        break;
+    case AUDIO_STREAM_TTS:
+        attr->content_type = AUDIO_CONTENT_TYPE_SPEECH;
+        attr->usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+        break;
+    default:
+        ALOGE("invalid stream type %d when converting to attributes", streamType);
+    }
+}
+
 #endif //AUDIO_POLICY_HELPER_H_
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 4edc1bf..8e0b8f8 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -88,8 +88,8 @@
      * user:    Pointer to context for use by the callback receiver.
      * info:    Pointer to optional parameter according to event type:
      *          - EVENT_MORE_DATA: pointer to AudioRecord::Buffer struct. The callback must not read
-     *            more bytes than indicated by 'size' field and update 'size' if fewer bytes are
-     *            consumed.
+     *                             more bytes than indicated by 'size' field and update 'size' if
+     *                             fewer bytes are consumed.
      *          - EVENT_OVERRUN: unused.
      *          - EVENT_MARKER: pointer to const uint32_t containing the marker position in frames.
      *          - EVENT_NEW_POS: pointer to const uint32_t containing the new position in frames.
@@ -106,6 +106,7 @@
      *  - BAD_VALUE: unsupported configuration
      * frameCount is guaranteed to be non-zero if status is NO_ERROR,
      * and is undefined otherwise.
+     * FIXME This API assumes a route, and so should be deprecated.
      */
 
      static status_t getMinFrameCount(size_t* frameCount,
@@ -152,6 +153,7 @@
      * transferType:       How data is transferred from AudioRecord.
      * flags:              See comments on audio_input_flags_t in <system/audio.h>
      * threadCanCallJava:  Not present in parameter list, and so is fixed at false.
+     * pAttributes:        if not NULL, supersedes inputSource for use case selection
      */
 
                         AudioRecord(audio_source_t inputSource,
@@ -164,7 +166,8 @@
                                     uint32_t notificationFrames = 0,
                                     int sessionId = AUDIO_SESSION_ALLOCATE,
                                     transfer_type transferType = TRANSFER_DEFAULT,
-                                    audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE);
+                                    audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
+                                    const audio_attributes_t* pAttributes = NULL);
 
     /* Terminates the AudioRecord and unregisters it from AudioFlinger.
      * Also destroys all resources associated with the AudioRecord.
@@ -198,7 +201,8 @@
                             bool threadCanCallJava = false,
                             int sessionId = AUDIO_SESSION_ALLOCATE,
                             transfer_type transferType = TRANSFER_DEFAULT,
-                            audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE);
+                            audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
+                            const audio_attributes_t* pAttributes = NULL);
 
     /* Result of constructing the AudioRecord. This must be checked for successful initialization
      * before using any AudioRecord API (except for set()), because using
@@ -219,7 +223,7 @@
             uint32_t    channelCount() const    { return mChannelCount; }
             size_t      frameCount() const  { return mFrameCount; }
             size_t      frameSize() const   { return mFrameSize; }
-            audio_source_t inputSource() const  { return mInputSource; }
+            audio_source_t inputSource() const  { return mAttributes.source; }
 
     /* After it's created the track is not active. Call start() to
      * make it active. If set, the callback will start being called.
@@ -413,6 +417,7 @@
 
                 void        pause();    // suspend thread from execution at next loop boundary
                 void        resume();   // allow thread to execute, if not requested to exit
+                void        wake();     // wake to handle changed notification conditions.
 
     private:
                 void        pauseInternal(nsecs_t ns = 0LL);
@@ -427,7 +432,9 @@
         bool                mPaused;    // whether thread is requested to pause at next loop entry
         bool                mPausedInt; // whether thread internally requests pause
         nsecs_t             mPausedNs;  // if mPausedInt then associated timeout, otherwise ignored
-        bool                mIgnoreNextPausedInt;   // whether to ignore next mPausedInt request
+        bool                mIgnoreNextPausedInt;   // skip any internal pause and go immediately
+                                        // to processAudioBuffer() as state may have changed
+                                        // since pause time calculated.
     };
 
             // body of AudioRecordThread::threadLoop()
@@ -489,7 +496,6 @@
     audio_format_t          mFormat;
     uint32_t                mChannelCount;
     size_t                  mFrameSize;         // app-level frame size == AudioFlinger frame size
-    audio_source_t          mInputSource;
     uint32_t                mLatency;           // in ms
     audio_channel_mask_t    mChannelMask;
     audio_input_flags_t     mFlags;
@@ -529,6 +535,7 @@
 
     sp<DeathNotifier>       mDeathNotifier;
     uint32_t                mSequence;              // incremented for each new IAudioRecord attempt
+    audio_attributes_t      mAttributes;
 };
 
 }; // namespace android
diff --git a/include/media/AudioResamplerPublic.h b/include/media/AudioResamplerPublic.h
index 97847a0..b705efa 100644
--- a/include/media/AudioResamplerPublic.h
+++ b/include/media/AudioResamplerPublic.h
@@ -26,4 +26,17 @@
 // TODO: replace with an API
 #define AUDIO_RESAMPLER_DOWN_RATIO_MAX 256
 
+// Returns the source frames needed to resample to destination frames.  This is not a precise
+// value and depends on the resampler (and possibly how it handles rounding internally).
+// Nevertheless, this should be an upper bound on the requirements of the resampler.
+// If srcSampleRate and dstSampleRate are equal, then it returns destination frames, which
+// may not be true if the resampler is asynchronous.
+static inline size_t sourceFramesNeeded(
+        uint32_t srcSampleRate, size_t dstFramesRequired, uint32_t dstSampleRate) {
+    // +1 for rounding - always do this even if matched ratio (resampler may use phases not ratio)
+    // +1 for additional sample needed for interpolation
+    return srcSampleRate == dstSampleRate ? dstFramesRequired :
+            size_t((uint64_t)dstFramesRequired * srcSampleRate / dstSampleRate + 1 + 1);
+}
+
 #endif // ANDROID_AUDIO_RESAMPLER_PUBLIC_H
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index f8c0198..ad5d6ed 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -18,6 +18,7 @@
 #define ANDROID_AUDIOSYSTEM_H_
 
 #include <hardware/audio_effect.h>
+#include <media/AudioPolicy.h>
 #include <media/IAudioFlingerClient.h>
 #include <media/IAudioPolicyServiceClient.h>
 #include <system/audio.h>
@@ -90,19 +91,20 @@
     static void setErrorCallback(audio_error_callback cb);
 
     // helper function to obtain AudioFlinger service handle
-    static const sp<IAudioFlinger>& get_audio_flinger();
+    static const sp<IAudioFlinger> get_audio_flinger();
 
     static float linearToLog(int volume);
     static int logToLinear(float volume);
 
     // Returned samplingRate and frameCount output values are guaranteed
     // to be non-zero if status == NO_ERROR
+    // FIXME This API assumes a route, and so should be deprecated.
     static status_t getOutputSamplingRate(uint32_t* samplingRate,
             audio_stream_type_t stream);
-    static status_t getOutputSamplingRateForAttr(uint32_t* samplingRate,
-                const audio_attributes_t *attr);
+    // FIXME This API assumes a route, and so should be deprecated.
     static status_t getOutputFrameCount(size_t* frameCount,
             audio_stream_type_t stream);
+    // FIXME This API assumes a route, and so should be deprecated.
     static status_t getOutputLatency(uint32_t* latency,
             audio_stream_type_t stream);
     static status_t getSamplingRate(audio_io_handle_t output,
@@ -111,21 +113,20 @@
     // audio_stream->get_buffer_size()/audio_stream_out_frame_size()
     static status_t getFrameCount(audio_io_handle_t output,
                                   size_t* frameCount);
-    // returns the audio output stream latency in ms. Corresponds to
+    // returns the audio output latency in ms. Corresponds to
     // audio_stream_out->get_latency()
     static status_t getLatency(audio_io_handle_t output,
                                uint32_t* latency);
 
-    static bool routedToA2dpOutput(audio_stream_type_t streamType);
-
     // return status NO_ERROR implies *buffSize > 0
+    // FIXME This API assumes a route, and so should deprecated.
     static status_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
         audio_channel_mask_t channelMask, size_t* buffSize);
 
     static status_t setVoiceVolume(float volume);
 
     // return the number of audio frames written by AudioFlinger to audio HAL and
-    // audio dsp to DAC since the specified output I/O handle has exited standby.
+    // audio dsp to DAC since the specified output has exited standby.
     // returned status (from utils/Errors.h) can be:
     // - NO_ERROR: successful operation, halFrames and dspFrames point to valid data
     // - INVALID_OPERATION: Not supported on current hardware platform
@@ -204,7 +205,7 @@
     // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
     //
     static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state,
-                                                const char *device_address);
+                                             const char *device_address, const char *device_name);
     static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                 const char *device_address);
     static status_t setPhoneState(audio_mode_t state);
@@ -219,7 +220,10 @@
                                         audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO,
                                         audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
                                         const audio_offload_info_t *offloadInfo = NULL);
-    static audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
+    static status_t getOutputForAttr(const audio_attributes_t *attr,
+                                        audio_io_handle_t *output,
+                                        audio_session_t session,
+                                        audio_stream_type_t *stream,
                                         uint32_t samplingRate = 0,
                                         audio_format_t format = AUDIO_FORMAT_DEFAULT,
                                         audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO,
@@ -227,20 +231,23 @@
                                         const audio_offload_info_t *offloadInfo = NULL);
     static status_t startOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
-                                int session);
+                                audio_session_t session);
     static status_t stopOutput(audio_io_handle_t output,
                                audio_stream_type_t stream,
-                               int session);
-    static void releaseOutput(audio_io_handle_t output);
+                               audio_session_t session);
+    static void releaseOutput(audio_io_handle_t output,
+                              audio_stream_type_t stream,
+                              audio_session_t session);
 
     // Client must successfully hand off the handle reference to AudioFlinger via openRecord(),
     // or release it with releaseInput().
-    static audio_io_handle_t getInput(audio_source_t inputSource,
+    static status_t getInputForAttr(const audio_attributes_t *attr,
+                                    audio_io_handle_t *input,
+                                    audio_session_t session,
                                     uint32_t samplingRate,
                                     audio_format_t format,
                                     audio_channel_mask_t channelMask,
-                                    int sessionId,
-                                    audio_input_flags_t);
+                                    audio_input_flags_t flags);
 
     static status_t startInput(audio_io_handle_t input,
                                audio_session_t session);
@@ -274,7 +281,7 @@
     // and output configuration cache (gOutputs)
     static void clearAudioConfigCache();
 
-    static const sp<IAudioPolicyService>& get_audio_policy_service();
+    static const sp<IAudioPolicyService> get_audio_policy_service();
 
     // helpers for android.media.AudioManager.getProperty(), see description there for meaning
     static uint32_t getPrimaryOutputSamplingRate();
@@ -322,6 +329,8 @@
 
     static audio_mode_t getPhoneState();
 
+    static status_t registerPolicyMixes(Vector<AudioMix> mixes, bool registration);
+
     // ----------------------------------------------------------------------------
 
     class AudioPortCallback : public RefBase
@@ -377,7 +386,11 @@
     friend class AudioFlingerClient;
     friend class AudioPolicyServiceClient;
 
-    static Mutex gLock;
+    static Mutex gLock;      // protects gAudioFlinger and gAudioErrorCallback,
+    static Mutex gLockCache; // protects gOutputs, gPrevInSamplingRate, gPrevInFormat,
+                             // gPrevInChannelMask and gInBuffSize
+    static Mutex gLockAPS;   // protects gAudioPolicyService and gAudioPolicyServiceClient
+    static Mutex gLockAPC;   // protects gAudioPortCallback
     static sp<IAudioFlinger> gAudioFlinger;
     static audio_error_callback gAudioErrorCallback;
 
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index b5256f0..3de0774 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -63,7 +63,7 @@
                                     // See AudioTimestamp for the information included with event.
     };
 
-    /* Client should declare Buffer on the stack and pass address to obtainBuffer()
+    /* Client should declare a Buffer and pass the address to obtainBuffer()
      * and releaseBuffer().  See also callback_t for EVENT_MORE_DATA.
      */
 
@@ -72,16 +72,20 @@
     public:
         // FIXME use m prefix
         size_t      frameCount;   // number of sample frames corresponding to size;
-                                  // on input it is the number of frames desired,
-                                  // on output is the number of frames actually filled
-                                  // (currently ignored, but will make the primary field in future)
+                                  // on input to obtainBuffer() it is the number of frames desired,
+                                  // on output from obtainBuffer() it is the number of available
+                                  //    [empty slots for] frames to be filled
+                                  // on input to releaseBuffer() it is currently ignored
 
         size_t      size;         // input/output in bytes == frameCount * frameSize
-                                  // on input it is unused
-                                  // on output is the number of bytes actually filled
-                                  // FIXME this is redundant with respect to frameCount,
-                                  // and TRANSFER_OBTAIN mode is broken for 8-bit data
-                                  // since we don't define the frame format
+                                  // on input to obtainBuffer() it is ignored
+                                  // on output from obtainBuffer() it is the number of available
+                                  //    [empty slots for] bytes to be filled,
+                                  //    which is frameCount * frameSize
+                                  // on input to releaseBuffer() it is the number of bytes to
+                                  //    release
+                                  // FIXME This is redundant with respect to frameCount.  Consider
+                                  //    removing size and making frameCount the primary field.
 
         union {
             void*       raw;
@@ -154,9 +158,9 @@
      * streamType:         Select the type of audio stream this track is attached to
      *                     (e.g. AUDIO_STREAM_MUSIC).
      * sampleRate:         Data source sampling rate in Hz.
-     * format:             Audio format.  For mixed tracks, any PCM format supported by server is OK
-     *                     or AUDIO_FORMAT_PCM_8_BIT which is handled on client side.  For direct
-     *                     and offloaded tracks, the possible format(s) depends on the output sink.
+     * format:             Audio format. For mixed tracks, any PCM format supported by server is OK.
+     *                     For direct and offloaded tracks, the possible format(s) depends on the
+     *                     output sink.
      * channelMask:        Channel mask, such that audio_is_output_channel(channelMask) is true.
      * frameCount:         Minimum size of track PCM buffer in frames. This defines the
      *                     application's contribution to the
@@ -193,7 +197,6 @@
 
     /* Creates an audio track and registers it with AudioFlinger.
      * With this constructor, the track is configured for static buffer mode.
-     * The format must not be 8-bit linear PCM.
      * Data to be rendered is passed in a shared memory buffer
      * identified by the argument sharedBuffer, which must be non-0.
      * The memory should be initialized to the desired data before calling start().
@@ -239,6 +242,9 @@
      * Parameters not listed in the AudioTrack constructors above:
      *
      * threadCanCallJava:  Whether callbacks are made from an attached thread and thus can call JNI.
+     *
+     * Internal state post condition:
+     *      (mStreamType == AUDIO_STREAM_DEFAULT) implies this AudioTrack has valid attributes
      */
             status_t    set(audio_stream_type_t streamType,
                             uint32_t sampleRate,
@@ -273,7 +279,7 @@
 
     /* getters, see constructors and set() */
 
-            audio_stream_type_t streamType() const { return mStreamType; }
+            audio_stream_type_t streamType() const;
             audio_format_t format() const   { return mFormat; }
 
     /* Return frame size in bytes, which for linear PCM is
@@ -484,10 +490,18 @@
      */
             status_t    attachAuxEffect(int effectId);
 
-    /* Obtains a buffer of up to "audioBuffer->frameCount" empty slots for frames.
+    /* Public API for TRANSFER_OBTAIN mode.
+     * Obtains a buffer of up to "audioBuffer->frameCount" empty slots for frames.
      * After filling these slots with data, the caller should release them with releaseBuffer().
      * If the track buffer is not full, obtainBuffer() returns as many contiguous
      * [empty slots for] frames as are available immediately.
+     *
+     * If nonContig is non-NULL, it is an output parameter that will be set to the number of
+     * additional non-contiguous frames that are predicted to be available immediately,
+     * if the client were to release the first frames and then call obtainBuffer() again.
+     * This value is only a prediction, and needs to be confirmed.
+     * It will be set to zero for an error return.
+     *
      * If the track buffer is full and track is stopped, obtainBuffer() returns WOULD_BLOCK
      * regardless of the value of waitCount.
      * If the track buffer is full and track is not stopped, obtainBuffer() blocks with a
@@ -496,7 +510,6 @@
      * is exhausted, at which point obtainBuffer() will either block
      * or return WOULD_BLOCK depending on the value of the "waitCount"
      * parameter.
-     * Each sample is 16-bit signed PCM.
      *
      * obtainBuffer() and releaseBuffer() are deprecated for direct use by applications,
      * which should use write() or callback EVENT_MORE_DATA instead.
@@ -508,24 +521,29 @@
      *
      * Buffer fields
      * On entry:
-     *  frameCount  number of frames requested
+     *  frameCount  number of [empty slots for] frames requested
+     *  size        ignored
+     *  raw         ignored
      * After error return:
      *  frameCount  0
      *  size        0
      *  raw         undefined
      * After successful return:
-     *  frameCount  actual number of frames available, <= number requested
+     *  frameCount  actual number of [empty slots for] frames available, <= number requested
      *  size        actual number of bytes available
      *  raw         pointer to the buffer
      */
-
     /* FIXME Deprecated public API for TRANSFER_OBTAIN mode */
-            status_t    obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
+            status_t    obtainBuffer(Buffer* audioBuffer, int32_t waitCount,
+                                size_t *nonContig = NULL)
                                 __attribute__((__deprecated__));
 
 private:
     /* If nonContig is non-NULL, it is an output parameter that will be set to the number of
-     * additional non-contiguous frames that are available immediately.
+     * additional non-contiguous frames that are predicted to be available immediately,
+     * if the client were to release the first frames and then call obtainBuffer() again.
+     * This value is only a prediction, and needs to be confirmed.
+     * It will be set to zero for an error return.
      * FIXME We could pass an array of Buffers instead of only one Buffer to obtainBuffer(),
      * in case the requested amount of frames is in two or more non-contiguous regions.
      * FIXME requested and elapsed are both relative times.  Consider changing to absolute time.
@@ -534,9 +552,17 @@
                                      struct timespec *elapsed = NULL, size_t *nonContig = NULL);
 public:
 
-    /* Release a filled buffer of "audioBuffer->frameCount" frames for AudioFlinger to process. */
+    /* Public API for TRANSFER_OBTAIN mode.
+     * Release a filled buffer of frames for AudioFlinger to process.
+     *
+     * Buffer fields:
+     *  frameCount  currently ignored but recommend to set to actual number of frames filled
+     *  size        actual number of bytes filled, must be multiple of frameSize
+     *  raw         ignored
+     *
+     */
     // FIXME make private when obtainBuffer() for TRANSFER_OBTAIN is removed
-            void        releaseBuffer(Buffer* audioBuffer);
+            void        releaseBuffer(const Buffer* audioBuffer);
 
     /* As a convenience we provide a write() interface to the audio buffer.
      * Input parameter 'size' is in byte units.
@@ -598,9 +624,6 @@
             AudioTrack& operator = (const AudioTrack& other);
 
             void        setAttributesFromStreamType(audio_stream_type_t streamType);
-            void        setStreamTypeFromAttributes(audio_attributes_t& aa);
-    /* paa is guaranteed non-NULL */
-            bool        isValidAttributes(const audio_attributes_t *paa);
 
     /* a small internal class to handle the callback */
     class AudioTrackThread : public Thread
@@ -614,6 +637,7 @@
 
                 void        pause();    // suspend thread from execution at next loop boundary
                 void        resume();   // allow thread to execute, if not requested to exit
+                void        wake();     // wake to handle changed notification conditions.
 
     private:
                 void        pauseInternal(nsecs_t ns = 0LL);
@@ -628,7 +652,9 @@
         bool                mPaused;    // whether thread is requested to pause at next loop entry
         bool                mPausedInt; // whether thread internally requests pause
         nsecs_t             mPausedNs;  // if mPausedInt then associated timeout, otherwise ignored
-        bool                mIgnoreNextPausedInt;   // whether to ignore next mPausedInt request
+        bool                mIgnoreNextPausedInt;   // skip any internal pause and go immediately
+                                        // to processAudioBuffer() as state may have changed
+                                        // since pause time calculated.
     };
 
             // body of AudioTrackThread::threadLoop()
@@ -680,7 +706,7 @@
 
     float                   mVolume[2];
     float                   mSendLevel;
-    mutable uint32_t        mSampleRate;            // mutable because getSampleRate() can update it.
+    mutable uint32_t        mSampleRate;            // mutable because getSampleRate() can update it
     size_t                  mFrameCount;            // corresponds to current IAudioTrack, value is
                                                     // reported back by AudioFlinger to the client
     size_t                  mReqFrameCount;         // frame count to request the first or next time
@@ -688,7 +714,8 @@
 
     // constant after constructor or set()
     audio_format_t          mFormat;                // as requested by client, not forced to 16-bit
-    audio_stream_type_t     mStreamType;
+    audio_stream_type_t     mStreamType;            // mStreamType == AUDIO_STREAM_DEFAULT implies
+                                                    // this AudioTrack has valid attributes
     uint32_t                mChannelCount;
     audio_channel_mask_t    mChannelMask;
     sp<IMemory>             mSharedBuffer;
@@ -697,10 +724,7 @@
     const audio_offload_info_t* mOffloadInfo;
     audio_attributes_t      mAttributes;
 
-    // mFrameSize is equal to mFrameSizeAF for non-PCM or 16-bit PCM data.  For 8-bit PCM data, it's
-    // twice as large as mFrameSize because data is expanded to 16-bit before it's stored in buffer.
-    size_t                  mFrameSize;             // app-level frame size
-    size_t                  mFrameSizeAF;           // AudioFlinger frame size
+    size_t                  mFrameSize;             // frame size in bytes
 
     status_t                mStatus;
 
@@ -731,13 +755,20 @@
     bool                    mRefreshRemaining;      // processAudioBuffer() should refresh
                                                     // mRemainingFrames and mRetryOnPartialBuffer
 
+                                                    // used for static track cbf and restoration
+    int32_t                 mLoopCount;             // last setLoop loopCount; zero means disabled
+    uint32_t                mLoopStart;             // last setLoop loopStart
+    uint32_t                mLoopEnd;               // last setLoop loopEnd
+    int32_t                 mLoopCountNotified;     // the last loopCount notified by callback.
+                                                    // mLoopCountNotified counts down, matching
+                                                    // the remaining loop count for static track
+                                                    // playback.
+
     // These are private to processAudioBuffer(), and are not protected by a lock
     uint32_t                mRemainingFrames;       // number of frames to request in obtainBuffer()
     bool                    mRetryOnPartialBuffer;  // sleep and retry after partial obtainBuffer()
     uint32_t                mObservedSequence;      // last observed value of mSequence
 
-    uint32_t                mLoopPeriod;            // in frames, zero means looping is disabled
-
     uint32_t                mMarkerPosition;        // in wrapping (overflow) frame units
     bool                    mMarkerReached;
     uint32_t                mNewPosition;           // in frames
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 31a14f0..f927a80 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -94,6 +94,8 @@
                                 sp<IMemory>& buffers,   // return value 0 means it follows cblk
                                 status_t *status) = 0;
 
+    // FIXME Surprisingly, sampleRate/format/frameCount/latency don't work for input handles
+
     /* query the audio hardware state. This state never changes,
      * and therefore can be cached.
      */
@@ -142,6 +144,7 @@
     virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
 
     // retrieve the audio recording buffer size
+    // FIXME This API assumes a route, and so should be deprecated.
     virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
             audio_channel_mask_t channelMask) const = 0;
 
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 16fe9cf..fecc6f1 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -25,6 +25,7 @@
 #include <utils/Errors.h>
 #include <binder/IInterface.h>
 #include <media/AudioSystem.h>
+#include <media/AudioPolicy.h>
 #include <media/IAudioPolicyServiceClient.h>
 
 #include <system/audio_policy.h>
@@ -43,7 +44,8 @@
     //
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
-                                              const char *device_address) = 0;
+                                              const char *device_address,
+                                              const char *device_name) = 0;
     virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                   const char *device_address) = 0;
     virtual status_t setPhoneState(audio_mode_t state) = 0;
@@ -56,25 +58,31 @@
                                         audio_channel_mask_t channelMask = 0,
                                         audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
                                         const audio_offload_info_t *offloadInfo = NULL) = 0;
-    virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
-                                            uint32_t samplingRate = 0,
-                                            audio_format_t format = AUDIO_FORMAT_DEFAULT,
-                                            audio_channel_mask_t channelMask = 0,
-                                            audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
-                                            const audio_offload_info_t *offloadInfo = NULL) = 0;
+    virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+                                        audio_io_handle_t *output,
+                                        audio_session_t session,
+                                        audio_stream_type_t *stream,
+                                        uint32_t samplingRate = 0,
+                                        audio_format_t format = AUDIO_FORMAT_DEFAULT,
+                                        audio_channel_mask_t channelMask = 0,
+                                        audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+                                        const audio_offload_info_t *offloadInfo = NULL) = 0;
     virtual status_t startOutput(audio_io_handle_t output,
                                  audio_stream_type_t stream,
-                                 int session = 0) = 0;
+                                 audio_session_t session) = 0;
     virtual status_t stopOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
-                                int session = 0) = 0;
-    virtual void releaseOutput(audio_io_handle_t output) = 0;
-    virtual audio_io_handle_t getInput(audio_source_t inputSource,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    int audioSession,
-                                    audio_input_flags_t flags) = 0;
+                                audio_session_t session) = 0;
+    virtual void releaseOutput(audio_io_handle_t output,
+                               audio_stream_type_t stream,
+                               audio_session_t session) = 0;
+    virtual status_t  getInputForAttr(const audio_attributes_t *attr,
+                                      audio_io_handle_t *input,
+                                      audio_session_t session,
+                                      uint32_t samplingRate,
+                                      audio_format_t format,
+                                      audio_channel_mask_t channelMask,
+                                      audio_input_flags_t flags) = 0;
     virtual status_t startInput(audio_io_handle_t input,
                                 audio_session_t session) = 0;
     virtual status_t stopInput(audio_io_handle_t input,
@@ -144,6 +152,8 @@
     virtual status_t releaseSoundTriggerSession(audio_session_t session) = 0;
 
     virtual audio_mode_t getPhoneState() = 0;
+
+    virtual status_t registerPolicyMixes(Vector<AudioMix> mixes, bool registration) = 0;
 };
 
 
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index db62cd5..4153c25 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -56,6 +56,7 @@
     virtual status_t        stop() = 0;
     virtual status_t        pause() = 0;
     virtual status_t        isPlaying(bool* state) = 0;
+    virtual status_t        setPlaybackRate(float rate) = 0;
     virtual status_t        seekTo(int msec) = 0;
     virtual status_t        getCurrentPosition(int* msec) = 0;
     virtual status_t        getDuration(int* msec) = 0;
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index d7e584a..49a3d61 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -49,19 +49,9 @@
 
     virtual sp<IMediaRecorder> createMediaRecorder() = 0;
     virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0;
-    virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0;
+    virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId = 0)
+            = 0;
 
-    virtual status_t         decode(
-            const sp<IMediaHTTPService> &httpService,
-            const char* url,
-            uint32_t *pSampleRate,
-            int* pNumChannels,
-            audio_format_t* pFormat,
-            const sp<IMemoryHeap>& heap, size_t *pSize) = 0;
-
-    virtual status_t         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
-                                    int* pNumChannels, audio_format_t* pFormat,
-                                    const sp<IMemoryHeap>& heap, size_t *pSize) = 0;
     virtual sp<IOMX>            getOMX() = 0;
     virtual sp<ICrypto>         makeCrypto() = 0;
     virtual sp<IDrm>            makeDrm() = 0;
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 3e67550..509c06b 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -41,7 +41,6 @@
     virtual status_t setOutputFormat(int of) = 0;
     virtual status_t setVideoEncoder(int ve) = 0;
     virtual status_t setAudioEncoder(int ae) = 0;
-    virtual status_t setOutputFile(const char* path) = 0;
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
     virtual status_t setVideoSize(int width, int height) = 0;
     virtual status_t setVideoFrameRate(int frames_per_second) = 0;
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 627f23b..6def65b 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -147,6 +147,7 @@
         INTERNAL_OPTION_SUSPEND,  // data is a bool
         INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY,  // data is an int64_t
         INTERNAL_OPTION_MAX_TIMESTAMP_GAP, // data is int64_t
+        INTERNAL_OPTION_MAX_FPS, // data is float
         INTERNAL_OPTION_START_TIME, // data is an int64_t
         INTERNAL_OPTION_TIME_LAPSE, // data is an int64_t[2]
     };
diff --git a/include/media/JetPlayer.h b/include/media/JetPlayer.h
index 388f767..63d1980 100644
--- a/include/media/JetPlayer.h
+++ b/include/media/JetPlayer.h
@@ -22,6 +22,7 @@
 #include <libsonivox/jet.h>
 #include <libsonivox/eas_types.h>
 #include <media/AudioTrack.h>
+#include <media/MidiIoWrapper.h>
 
 
 namespace android {
@@ -86,15 +87,13 @@
 
     int                 mMaxTracks; // max number of MIDI tracks, usually 32
     EAS_DATA_HANDLE     mEasData;
-    EAS_FILE_LOCATOR    mEasJetFileLoc;
+    sp<MidiIoWrapper>   mIoWrapper;
     EAS_PCM*            mAudioBuffer;// EAS renders the MIDI data into this buffer,
     sp<AudioTrack>      mAudioTrack; // and we play it in this audio track
     int                 mTrackBufferSize;
     S_JET_STATUS        mJetStatus;
     S_JET_STATUS        mPreviousJetStatus;
 
-    char                mJetFilePath[PATH_MAX];
-
     class JetPlayerThread : public Thread {
     public:
         JetPlayerThread(JetPlayer *player) : mPlayer(player) {
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index c412299..d6fe390 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -43,8 +43,6 @@
 template<typename T> class SortedVector;
 
 enum player_type {
-    PV_PLAYER = 1,
-    SONIVOX_PLAYER = 2,
     STAGEFRIGHT_PLAYER = 3,
     NU_PLAYER = 4,
     // Test players are available only in the 'test' and 'eng' builds.
@@ -90,7 +88,6 @@
 
         virtual             ~AudioSink() {}
         virtual bool        ready() const = 0; // audio output is open and ready
-        virtual bool        realtime() const = 0; // audio output is real-time output
         virtual ssize_t     bufferSize() const = 0;
         virtual ssize_t     frameCount() const = 0;
         virtual ssize_t     channelCount() const = 0;
@@ -116,7 +113,19 @@
                 const audio_offload_info_t *offloadInfo = NULL) = 0;
 
         virtual status_t    start() = 0;
-        virtual ssize_t     write(const void* buffer, size_t size) = 0;
+
+        /* Input parameter |size| is in byte units stored in |buffer|.
+         * Data is copied over and actual number of bytes written (>= 0)
+         * is returned, or no data is copied and a negative status code
+         * is returned (even when |blocking| is true).
+         * When |blocking| is false, AudioSink will immediately return after
+         * part of or full |buffer| is copied over.
+         * When |blocking| is true, AudioSink will wait to copy the entire
+         * buffer, unless an error occurs or the copy operation is
+         * prematurely stopped.
+         */
+        virtual ssize_t     write(const void* buffer, size_t size, bool blocking = true) = 0;
+
         virtual void        stop() = 0;
         virtual void        flush() = 0;
         virtual void        pause() = 0;
@@ -159,6 +168,7 @@
     virtual status_t    stop() = 0;
     virtual status_t    pause() = 0;
     virtual bool        isPlaying() = 0;
+    virtual status_t    setPlaybackRate(float rate) { return INVALID_OPERATION; }
     virtual status_t    seekTo(int msec) = 0;
     virtual status_t    getCurrentPosition(int *msec) = 0;
     virtual status_t    getDuration(int *msec) = 0;
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index d7ac302..f55063e 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -43,7 +43,6 @@
     virtual status_t setCamera(const sp<ICamera>& camera,
                                const sp<ICameraRecordingProxy>& proxy) = 0;
     virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface) = 0;
-    virtual status_t setOutputFile(const char *path) = 0;
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
     virtual status_t setOutputFileAuxiliary(int fd) {return INVALID_OPERATION;}
     virtual status_t setParameters(const String8& params) = 0;
diff --git a/include/media/MidiIoWrapper.h b/include/media/MidiIoWrapper.h
new file mode 100644
index 0000000..e6f8cf7
--- /dev/null
+++ b/include/media/MidiIoWrapper.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 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 MIDI_IO_WRAPPER_H_
+#define MIDI_IO_WRAPPER_H_
+
+#include <libsonivox/eas_types.h>
+
+#include "media/stagefright/DataSource.h"
+
+namespace android {
+
+class MidiIoWrapper : public RefBase {
+public:
+    MidiIoWrapper(const char *path);
+    MidiIoWrapper(int fd, off64_t offset, int64_t size);
+    MidiIoWrapper(const sp<DataSource> &source);
+
+    ~MidiIoWrapper();
+
+    int readAt(void *buffer, int offset, int size);
+    int size();
+
+    EAS_FILE_LOCATOR getLocator();
+
+private:
+    int mFd;
+    off64_t mBase;
+    int64_t  mLength;
+    sp<DataSource> mDataSource;
+    EAS_FILE mEasFile;
+};
+
+
+}  // namespace android
+
+#endif // MIDI_IO_WRAPPER_H_
diff --git a/include/media/SingleStateQueue.h b/include/media/SingleStateQueue.h
index 04c5fd0..d423962 100644
--- a/include/media/SingleStateQueue.h
+++ b/include/media/SingleStateQueue.h
@@ -21,6 +21,7 @@
 // Non-blocking single-reader / single-writer multi-word atomic load / store
 
 #include <stdint.h>
+#include <cutils/atomic.h>
 
 namespace android {
 
@@ -31,6 +32,12 @@
     class Mutator;
     class Observer;
 
+    enum SSQ_STATUS {
+        SSQ_PENDING, /* = 0 */
+        SSQ_READ,
+        SSQ_DONE,
+    };
+
     struct Shared {
         // needs to be part of a union so don't define constructor or destructor
 
@@ -41,28 +48,56 @@
         void                init() { mAck = 0; mSequence = 0; }
 
         volatile int32_t    mAck;
-#if 0
-        int                 mPad[7];
-        // cache line boundary
-#endif
         volatile int32_t    mSequence;
         T                   mValue;
     };
 
     class Mutator {
     public:
-        Mutator(Shared *shared);
-        /*virtual*/ ~Mutator() { }
+        Mutator(Shared *shared)
+            : mSequence(0), mShared(shared)
+        {
+            // exactly one of Mutator and Observer must initialize, currently it is Observer
+            // shared->init();
+        }
 
         // push new value onto state queue, overwriting previous value;
         // returns a sequence number which can be used with ack()
-        int32_t push(const T& value);
+        int32_t push(const T& value)
+        {
+            Shared *shared = mShared;
+            int32_t sequence = mSequence;
+            sequence++;
+            android_atomic_acquire_store(sequence, &shared->mSequence);
+            shared->mValue = value;
+            sequence++;
+            android_atomic_release_store(sequence, &shared->mSequence);
+            mSequence = sequence;
+            // consider signalling a futex here, if we know that observer is waiting
+            return sequence;
+        }
 
-        // return true if most recent push has been observed
-        bool ack();
+        // returns the status of the last state push.  This may be a stale value.
+        //
+        // SSQ_PENDING, or 0, means it has not been observed
+        // SSQ_READ means it has been read
+        // SSQ_DONE means it has been acted upon, after Observer::done() is called
+        enum SSQ_STATUS ack() const
+        {
+            // in the case of SSQ_DONE, prevent any subtle data-races of subsequent reads
+            // being performed (out-of-order) before the ack read, should the caller be
+            // depending on sequentiality of reads.
+            const int32_t ack = android_atomic_acquire_load(&mShared->mAck);
+            return ack - mSequence & ~1 ? SSQ_PENDING /* seq differ */ :
+                    ack & 1 ? SSQ_DONE : SSQ_READ;
+        }
 
         // return true if a push with specified sequence number or later has been observed
-        bool ack(int32_t sequence);
+        bool ack(int32_t sequence) const
+        {
+            // this relies on 2's complement rollover to detect an ancient sequence number
+            return mShared->mAck - sequence >= 0;
+        }
 
     private:
         int32_t     mSequence;
@@ -71,11 +106,54 @@
 
     class Observer {
     public:
-        Observer(Shared *shared);
-        /*virtual*/ ~Observer() { }
+        Observer(Shared *shared)
+            : mSequence(0), mSeed(1), mShared(shared)
+        {
+            // exactly one of Mutator and Observer must initialize, currently it is Observer
+            shared->init();
+        }
 
         // return true if value has changed
-        bool poll(T& value);
+        bool poll(T& value)
+        {
+            Shared *shared = mShared;
+            int32_t before = shared->mSequence;
+            if (before == mSequence) {
+                return false;
+            }
+            for (int tries = 0; ; ) {
+                const int MAX_TRIES = 5;
+                if (before & 1) {
+                    if (++tries >= MAX_TRIES) {
+                        return false;
+                    }
+                    before = shared->mSequence;
+                } else {
+                    android_memory_barrier();
+                    T temp = shared->mValue;
+                    int32_t after = android_atomic_release_load(&shared->mSequence);
+                    if (after == before) {
+                        value = temp;
+                        shared->mAck = before;
+                        mSequence = before; // mSequence is even after poll success
+                        return true;
+                    }
+                    if (++tries >= MAX_TRIES) {
+                        return false;
+                    }
+                    before = after;
+                }
+            }
+        }
+
+        // (optional) used to indicate to the Mutator that the state that has been polled
+        // has also been acted upon.
+        void done()
+        {
+            const int32_t ack = mShared->mAck + 1;
+            // ensure all previous writes have been performed.
+            android_atomic_release_store(ack, &mShared->mAck); // mSequence is odd after "done"
+        }
 
     private:
         int32_t     mSequence;
diff --git a/include/media/SoundPool.h b/include/media/SoundPool.h
deleted file mode 100644
index 5830475..0000000
--- a/include/media/SoundPool.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2007 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 SOUNDPOOL_H_
-#define SOUNDPOOL_H_
-
-#include <utils/threads.h>
-#include <utils/List.h>
-#include <utils/Vector.h>
-#include <utils/KeyedVector.h>
-#include <media/AudioTrack.h>
-#include <binder/MemoryHeapBase.h>
-#include <binder/MemoryBase.h>
-
-namespace android {
-
-static const int IDLE_PRIORITY = -1;
-
-// forward declarations
-class SoundEvent;
-class SoundPoolThread;
-class SoundPool;
-
-// for queued events
-class SoundPoolEvent {
-public:
-    SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
-        mMsg(msg), mArg1(arg1), mArg2(arg2) {}
-    int         mMsg;
-    int         mArg1;
-    int         mArg2;
-    enum MessageType { INVALID, SAMPLE_LOADED };
-};
-
-// callback function prototype
-typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
-
-// tracks samples used by application
-class Sample  : public RefBase {
-public:
-    enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
-    Sample(int sampleID, const char* url);
-    Sample(int sampleID, int fd, int64_t offset, int64_t length);
-    ~Sample();
-    int sampleID() { return mSampleID; }
-    int numChannels() { return mNumChannels; }
-    int sampleRate() { return mSampleRate; }
-    audio_format_t format() { return mFormat; }
-    size_t size() { return mSize; }
-    int state() { return mState; }
-    uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
-    status_t doLoad();
-    void startLoad() { mState = LOADING; }
-    sp<IMemory> getIMemory() { return mData; }
-
-    // hack
-    void init(int numChannels, int sampleRate, audio_format_t format, size_t size,
-            sp<IMemory> data ) {
-        mNumChannels = numChannels; mSampleRate = sampleRate; mFormat = format; mSize = size;
-            mData = data; }
-
-private:
-    void init();
-
-    size_t              mSize;
-    volatile int32_t    mRefCount;
-    uint16_t            mSampleID;
-    uint16_t            mSampleRate;
-    uint8_t             mState : 3;
-    uint8_t             mNumChannels : 2;
-    audio_format_t      mFormat;
-    int                 mFd;
-    int64_t             mOffset;
-    int64_t             mLength;
-    char*               mUrl;
-    sp<IMemory>         mData;
-    sp<MemoryHeapBase>  mHeap;
-};
-
-// stores pending events for stolen channels
-class SoundEvent
-{
-public:
-    SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
-            mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
-    void set(const sp<Sample>& sample, int channelID, float leftVolume,
-            float rightVolume, int priority, int loop, float rate);
-    sp<Sample>      sample() { return mSample; }
-    int             channelID() { return mChannelID; }
-    float           leftVolume() { return mLeftVolume; }
-    float           rightVolume() { return mRightVolume; }
-    int             priority() { return mPriority; }
-    int             loop() { return mLoop; }
-    float           rate() { return mRate; }
-    void            clear() { mChannelID = 0; mSample.clear(); }
-
-protected:
-    sp<Sample>      mSample;
-    int             mChannelID;
-    float           mLeftVolume;
-    float           mRightVolume;
-    int             mPriority;
-    int             mLoop;
-    float           mRate;
-};
-
-// for channels aka AudioTracks
-class SoundChannel : public SoundEvent {
-public:
-    enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
-    SoundChannel() : mState(IDLE), mNumChannels(1),
-            mPos(0), mToggle(0), mAutoPaused(false) {}
-    ~SoundChannel();
-    void init(SoundPool* soundPool);
-    void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
-            int priority, int loop, float rate);
-    void setVolume_l(float leftVolume, float rightVolume);
-    void setVolume(float leftVolume, float rightVolume);
-    void stop_l();
-    void stop();
-    void pause();
-    void autoPause();
-    void resume();
-    void autoResume();
-    void setRate(float rate);
-    int state() { return mState; }
-    void setPriority(int priority) { mPriority = priority; }
-    void setLoop(int loop);
-    int numChannels() { return mNumChannels; }
-    void clearNextEvent() { mNextEvent.clear(); }
-    void nextEvent();
-    int nextChannelID() { return mNextEvent.channelID(); }
-    void dump();
-
-private:
-    static void callback(int event, void* user, void *info);
-    void process(int event, void *info, unsigned long toggle);
-    bool doStop_l();
-
-    SoundPool*          mSoundPool;
-    sp<AudioTrack>      mAudioTrack;
-    SoundEvent          mNextEvent;
-    Mutex               mLock;
-    int                 mState;
-    int                 mNumChannels;
-    int                 mPos;
-    int                 mAudioBufferSize;
-    unsigned long       mToggle;
-    bool                mAutoPaused;
-};
-
-// application object for managing a pool of sounds
-class SoundPool {
-    friend class SoundPoolThread;
-    friend class SoundChannel;
-public:
-    SoundPool(int maxChannels, const audio_attributes_t* pAttributes);
-    ~SoundPool();
-    int load(const char* url, int priority);
-    int load(int fd, int64_t offset, int64_t length, int priority);
-    bool unload(int sampleID);
-    int play(int sampleID, float leftVolume, float rightVolume, int priority,
-            int loop, float rate);
-    void pause(int channelID);
-    void autoPause();
-    void resume(int channelID);
-    void autoResume();
-    void stop(int channelID);
-    void setVolume(int channelID, float leftVolume, float rightVolume);
-    void setPriority(int channelID, int priority);
-    void setLoop(int channelID, int loop);
-    void setRate(int channelID, float rate);
-    const audio_attributes_t* attributes() { return &mAttributes; }
-
-    // called from SoundPoolThread
-    void sampleLoaded(int sampleID);
-
-    // called from AudioTrack thread
-    void done_l(SoundChannel* channel);
-
-    // callback function
-    void setCallback(SoundPoolCallback* callback, void* user);
-    void* getUserData() { return mUserData; }
-
-private:
-    SoundPool() {} // no default constructor
-    bool startThreads();
-    void doLoad(sp<Sample>& sample);
-    sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
-    SoundChannel* findChannel (int channelID);
-    SoundChannel* findNextChannel (int channelID);
-    SoundChannel* allocateChannel_l(int priority);
-    void moveToFront_l(SoundChannel* channel);
-    void notify(SoundPoolEvent event);
-    void dump();
-
-    // restart thread
-    void addToRestartList(SoundChannel* channel);
-    void addToStopList(SoundChannel* channel);
-    static int beginThread(void* arg);
-    int run();
-    void quit();
-
-    Mutex                   mLock;
-    Mutex                   mRestartLock;
-    Condition               mCondition;
-    SoundPoolThread*        mDecodeThread;
-    SoundChannel*           mChannelPool;
-    List<SoundChannel*>     mChannels;
-    List<SoundChannel*>     mRestart;
-    List<SoundChannel*>     mStop;
-    DefaultKeyedVector< int, sp<Sample> >   mSamples;
-    int                     mMaxChannels;
-    audio_attributes_t      mAttributes;
-    int                     mAllocated;
-    int                     mNextSampleID;
-    int                     mNextChannelID;
-    bool                    mQuit;
-
-    // callback
-    Mutex                   mCallbackLock;
-    SoundPoolCallback*      mCallback;
-    void*                   mUserData;
-};
-
-} // end namespace android
-
-#endif /*SOUNDPOOL_H_*/
diff --git a/include/media/StringArray.h b/include/media/StringArray.h
index ae47085..48d98bf 100644
--- a/include/media/StringArray.h
+++ b/include/media/StringArray.h
@@ -16,7 +16,7 @@
 
 //
 // Sortable array of strings.  STL-ish, but STL-free.
-//  
+//
 #ifndef _LIBS_MEDIA_STRING_ARRAY_H
 #define _LIBS_MEDIA_STRING_ARRAY_H
 
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index 98c4332..8406ed6 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -17,11 +17,12 @@
 #ifndef ANDROID_TONEGENERATOR_H_
 #define ANDROID_TONEGENERATOR_H_
 
-#include <utils/RefBase.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
 #include <media/AudioSystem.h>
 #include <media/AudioTrack.h>
+#include <utils/Compat.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
 
 namespace android {
 
@@ -207,7 +208,7 @@
     static const unsigned int TONEGEN_MAX_WAVES = 3;     // Maximun number of sine waves in a tone segment
     static const unsigned int TONEGEN_MAX_SEGMENTS = 12;  // Maximun number of segments in a tone descriptor
     static const unsigned int TONEGEN_INF = 0xFFFFFFFF;  // Represents infinite time duration
-    static const float TONEGEN_GAIN = 0.9;  // Default gain passed to  WaveGenerator().
+    static const CONSTEXPR float TONEGEN_GAIN = 0.9;  // Default gain passed to  WaveGenerator().
 
     // ToneDescriptor class contains all parameters needed to generate a tone:
     //    - The array waveFreq[]:
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 9cc208e..808e893 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -220,6 +220,7 @@
             status_t        stop();
             status_t        pause();
             bool            isPlaying();
+            status_t        setPlaybackRate(float rate);
             status_t        getVideoWidth(int *w);
             status_t        getVideoHeight(int *h);
             status_t        seekTo(int msec);
@@ -232,17 +233,6 @@
             bool            isLooping();
             status_t        setVolume(float leftVolume, float rightVolume);
             void            notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
-    static  status_t        decode(
-            const sp<IMediaHTTPService> &httpService,
-            const char* url,
-            uint32_t *pSampleRate,
-            int* pNumChannels,
-            audio_format_t* pFormat,
-            const sp<IMemoryHeap>& heap,
-            size_t *pSize);
-    static  status_t        decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
-                                   int* pNumChannels, audio_format_t* pFormat,
-                                   const sp<IMemoryHeap>& heap, size_t *pSize);
             status_t        invoke(const Parcel& request, Parcel *reply);
             status_t        setMetadataFilter(const Parcel& filter);
             status_t        getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
@@ -285,6 +275,7 @@
     int                         mVideoWidth;
     int                         mVideoHeight;
     int                         mAudioSessionId;
+    float                       mPlaybackRate;
     float                       mSendLevel;
     struct sockaddr_in          mRetransmitEndpoint;
     bool                        mRetransmitEndpointValid;
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index b0a62a7..74a6469 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -221,7 +221,6 @@
     status_t    setOutputFormat(int of);
     status_t    setVideoEncoder(int ve);
     status_t    setAudioEncoder(int ae);
-    status_t    setOutputFile(const char* path);
     status_t    setOutputFile(int fd, int64_t offset, int64_t length);
     status_t    setVideoSize(int width, int height);
     status_t    setVideoFrameRate(int frames_per_second);
diff --git a/include/media/nbaio/NBAIO.h b/include/media/nbaio/NBAIO.h
index d422576..d9bbc8d 100644
--- a/include/media/nbaio/NBAIO.h
+++ b/include/media/nbaio/NBAIO.h
@@ -231,7 +231,8 @@
     virtual status_t getTimestamp(AudioTimestamp& timestamp) { return INVALID_OPERATION; }
 
 protected:
-    NBAIO_Sink(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesWritten(0) { }
+    NBAIO_Sink(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesWritten(0)
+            { }
     virtual ~NBAIO_Sink() { }
 
     // Implementations are free to ignore these if they don't need them
@@ -322,7 +323,8 @@
     virtual void    onTimestamp(const AudioTimestamp& timestamp) { }
 
 protected:
-    NBAIO_Source(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesRead(0) { }
+    NBAIO_Source(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesRead(0)
+            { }
     virtual ~NBAIO_Source() { }
 
     // Implementations are free to ignore these if they don't need them
diff --git a/include/media/nbaio/NBLog.h b/include/media/nbaio/NBLog.h
index bcbbc04..1297b51 100644
--- a/include/media/nbaio/NBLog.h
+++ b/include/media/nbaio/NBLog.h
@@ -21,7 +21,7 @@
 
 #include <binder/IMemory.h>
 #include <utils/Mutex.h>
-#include <media/nbaio/roundup.h>
+#include <audio_utils/roundup.h>
 
 namespace android {
 
diff --git a/include/media/nbaio/roundup.h b/include/media/nbaio/roundup.h
deleted file mode 100644
index 4c3cc25..0000000
--- a/include/media/nbaio/roundup.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2012 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 ROUNDUP_H
-#define ROUNDUP_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Round up to the next highest power of 2
-unsigned roundup(unsigned v);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  // ROUNDUP_H
diff --git a/include/media/stagefright/AACWriter.h b/include/media/stagefright/AACWriter.h
index d22707a..86417a5 100644
--- a/include/media/stagefright/AACWriter.h
+++ b/include/media/stagefright/AACWriter.h
@@ -27,7 +27,6 @@
 struct MetaData;
 
 struct AACWriter : public MediaWriter {
-    AACWriter(const char *filename);
     AACWriter(int fd);
 
     status_t initCheck() const;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index fcccc6d..aa91485 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -78,7 +78,7 @@
 
     static bool isFlexibleColorFormat(
             const sp<IOMX> &omx, IOMX::node_id node,
-            uint32_t colorFormat, OMX_U32 *flexibleEquivalent);
+            uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent);
 
     // Returns 0 if configuration is not supported.  NOTE: this is treated by
     // some OMX components as auto level, and by others as invalid level.
@@ -131,6 +131,7 @@
     enum {
         kFlagIsSecure                                 = 1,
         kFlagPushBlankBuffersToNativeWindowOnShutdown = 2,
+        kFlagIsGrallocUsageProtected                  = 4,
     };
 
     struct BufferInfo {
@@ -182,6 +183,7 @@
     sp<ANativeWindow> mNativeWindow;
     sp<AMessage> mInputFormat;
     sp<AMessage> mOutputFormat;
+    sp<AMessage> mBaseOutputFormat;
 
     Vector<BufferInfo> mBuffers[2];
     bool mPortEOS[2];
@@ -212,6 +214,7 @@
 
     int64_t mRepeatFrameDelayUs;
     int64_t mMaxPtsGapUs;
+    float mMaxFps;
 
     int64_t mTimePerFrameUs;
     int64_t mTimePerCaptureUs;
@@ -249,12 +252,13 @@
     status_t setVideoPortFormatType(
             OMX_U32 portIndex,
             OMX_VIDEO_CODINGTYPE compressionFormat,
-            OMX_COLOR_FORMATTYPE colorFormat);
+            OMX_COLOR_FORMATTYPE colorFormat,
+            bool usingNativeBuffers = false);
 
-    status_t setSupportedOutputFormat();
+    status_t setSupportedOutputFormat(bool getLegacyFlexibleFormat);
 
     status_t setupVideoDecoder(
-            const char *mime, const sp<AMessage> &msg);
+            const char *mime, const sp<AMessage> &msg, bool usingNativeBuffers);
 
     status_t setupVideoEncoder(
             const char *mime, const sp<AMessage> &msg);
@@ -262,7 +266,7 @@
     status_t setVideoFormatOnPort(
             OMX_U32 portIndex,
             int32_t width, int32_t height,
-            OMX_VIDEO_CODINGTYPE compressionFormat);
+            OMX_VIDEO_CODINGTYPE compressionFormat, float frameRate = -1.0);
 
     typedef struct drcParams {
         int32_t drcCut;
@@ -281,6 +285,8 @@
 
     status_t setupAC3Codec(bool encoder, int32_t numChannels, int32_t sampleRate);
 
+    status_t setupEAC3Codec(bool encoder, int32_t numChannels, int32_t sampleRate);
+
     status_t selectAudioPortFormat(
             OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat);
 
@@ -293,6 +299,8 @@
     status_t setupRawAudioFormat(
             OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels);
 
+    status_t setPriority(int32_t priority);
+
     status_t setMinBufferSize(OMX_U32 portIndex, size_t size);
 
     status_t setupMPEG4EncoderParameters(const sp<AMessage> &msg);
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h
index 392f968..bac878b 100644
--- a/include/media/stagefright/AMRWriter.h
+++ b/include/media/stagefright/AMRWriter.h
@@ -29,7 +29,6 @@
 struct MetaData;
 
 struct AMRWriter : public MediaWriter {
-    AMRWriter(const char *filename);
     AMRWriter(int fd);
 
     status_t initCheck() const;
diff --git a/include/media/stagefright/BufferProducerWrapper.h b/include/media/stagefright/BufferProducerWrapper.h
index d8acf30..4caa2c6 100644
--- a/include/media/stagefright/BufferProducerWrapper.h
+++ b/include/media/stagefright/BufferProducerWrapper.h
@@ -19,6 +19,7 @@
 #define BUFFER_PRODUCER_WRAPPER_H_
 
 #include <gui/IGraphicBufferProducer.h>
+#include <media/stagefright/foundation/ABase.h>
 
 namespace android {
 
diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h
index 2e2922e..3d7960b 100644
--- a/include/media/stagefright/MPEG2TSWriter.h
+++ b/include/media/stagefright/MPEG2TSWriter.h
@@ -29,7 +29,6 @@
 
 struct MPEG2TSWriter : public MediaWriter {
     MPEG2TSWriter(int fd);
-    MPEG2TSWriter(const char *filename);
 
     MPEG2TSWriter(
             void *cookie,
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 26ce5f9..a195fe8 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -26,13 +26,13 @@
 
 namespace android {
 
+class AMessage;
 class MediaBuffer;
 class MediaSource;
 class MetaData;
 
 class MPEG4Writer : public MediaWriter {
 public:
-    MPEG4Writer(const char *filename);
     MPEG4Writer(int fd);
 
     // Limitations
@@ -49,6 +49,7 @@
     virtual status_t dump(int fd, const Vector<String16>& args);
 
     void beginBox(const char *fourcc);
+    void beginBox(uint32_t id);
     void writeInt8(int8_t x);
     void writeInt16(int16_t x);
     void writeInt32(int32_t x);
@@ -63,6 +64,7 @@
     int32_t getTimeScale() const { return mTimeScale; }
 
     status_t setGeoData(int latitudex10000, int longitudex10000);
+    status_t setCaptureRate(float captureFps);
     virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; }
     virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; }
 
@@ -89,6 +91,7 @@
     off64_t mFreeBoxOffset;
     bool mStreamableFile;
     off64_t mEstimatedMoovBoxSize;
+    off64_t mMoovExtraSize;
     uint32_t mInterleaveDurationUs;
     int32_t mTimeScale;
     int64_t mStartTimestampUs;
@@ -103,6 +106,8 @@
 
     List<off64_t> mBoxes;
 
+    sp<AMessage> mMetaKeys;
+
     void setStartTimestampUs(int64_t timeUs);
     int64_t getStartTimestampUs();  // Not const
     status_t startTracks(MetaData *params);
@@ -196,6 +201,12 @@
     void writeGeoDataBox();
     void writeLatitude(int degreex10000);
     void writeLongitude(int degreex10000);
+
+    void addDeviceMeta();
+    void writeHdlr();
+    void writeKeys();
+    void writeIlst();
+    void writeMetaBox();
     void sendSessionSummary();
     void release();
     status_t reset();
diff --git a/include/media/stagefright/MediaClock.h b/include/media/stagefright/MediaClock.h
new file mode 100644
index 0000000..660764f
--- /dev/null
+++ b/include/media/stagefright/MediaClock.h
@@ -0,0 +1,77 @@
+/*
+ * 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 MEDIA_CLOCK_H_
+
+#define MEDIA_CLOCK_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct AMessage;
+
+struct MediaClock : public RefBase {
+    MediaClock();
+
+    void setStartingTimeMedia(int64_t startingTimeMediaUs);
+
+    void clearAnchor();
+    // It's required to use timestamp of just rendered frame as
+    // anchor time in paused state.
+    void updateAnchor(
+        int64_t anchorTimeMediaUs,
+        int64_t anchorTimeRealUs,
+        int64_t maxTimeMediaUs = INT64_MAX);
+
+    void updateMaxTimeMedia(int64_t maxTimeMediaUs);
+
+    void setPlaybackRate(float rate);
+
+    // query media time corresponding to real time |realUs|, and save the
+    // result in |outMediaUs|.
+    status_t getMediaTime(int64_t realUs,
+                          int64_t *outMediaUs,
+                          bool allowPastMaxTime = false);
+    // query real time corresponding to media time |targetMediaUs|.
+    // The result is saved in |outRealUs|.
+    status_t getRealTimeFor(int64_t targetMediaUs, int64_t *outRealUs);
+
+protected:
+    virtual ~MediaClock();
+
+private:
+    status_t getMediaTime_l(int64_t realUs,
+                            int64_t *outMediaUs,
+                            bool allowPastMaxTime);
+
+    Mutex mLock;
+
+    int64_t mAnchorTimeMediaUs;
+    int64_t mAnchorTimeRealUs;
+    int64_t mMaxTimeMediaUs;
+    int64_t mStartingTimeMediaUs;
+
+    float mPlaybackRate;
+
+    DISALLOW_EVIL_CONSTRUCTORS(MediaClock);
+};
+
+}  // namespace android
+
+#endif  // MEDIA_CLOCK_H_
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 54a4e8b..8241e19 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -27,6 +27,7 @@
 
 struct ABuffer;
 struct AMessage;
+struct AReplyToken;
 struct AString;
 struct CodecBase;
 struct ICrypto;
@@ -194,7 +195,7 @@
     };
 
     enum {
-        kFlagIsSoftwareCodec            = 1,
+        kFlagUsesSoftwareRenderer       = 1,
         kFlagOutputFormatChanged        = 2,
         kFlagOutputBuffersChanged       = 4,
         kFlagStickyError                = 8,
@@ -222,7 +223,7 @@
     sp<ALooper> mCodecLooper;
     sp<CodecBase> mCodec;
     AString mComponentName;
-    uint32_t mReplyID;
+    sp<AReplyToken> mReplyID;
     uint32_t mFlags;
     status_t mStickyError;
     sp<Surface> mNativeWindow;
@@ -249,10 +250,10 @@
     Vector<BufferInfo> mPortBuffers[2];
 
     int32_t mDequeueInputTimeoutGeneration;
-    uint32_t mDequeueInputReplyID;
+    sp<AReplyToken> mDequeueInputReplyID;
 
     int32_t mDequeueOutputTimeoutGeneration;
-    uint32_t mDequeueOutputReplyID;
+    sp<AReplyToken> mDequeueOutputReplyID;
 
     sp<ICrypto> mCrypto;
 
@@ -267,7 +268,7 @@
     static status_t PostAndAwaitResponse(
             const sp<AMessage> &msg, sp<AMessage> *response);
 
-    static void PostReplyWithError(int32_t replyID, int32_t err);
+    static void PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err);
 
     status_t init(const AString &name, bool nameIsType, bool encoder);
 
@@ -283,8 +284,8 @@
             size_t portIndex, size_t index,
             sp<ABuffer> *buffer, sp<AMessage> *format);
 
-    bool handleDequeueInputBuffer(uint32_t replyID, bool newRequest = false);
-    bool handleDequeueOutputBuffer(uint32_t replyID, bool newRequest = false);
+    bool handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
+    bool handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
     void cancelPendingDequeueOperations();
 
     void extractCSD(const sp<AMessage> &format);
diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h
index 8605d99..c2bbe4d 100644
--- a/include/media/stagefright/MediaCodecList.h
+++ b/include/media/stagefright/MediaCodecList.h
@@ -52,6 +52,12 @@
     static sp<IMediaCodecList> getLocalInstance();
 
 private:
+    class BinderDeathObserver : public IBinder::DeathRecipient {
+        void binderDied(const wp<IBinder> &the_late_who __unused);
+    };
+
+    static sp<BinderDeathObserver> sBinderDeathObserver;
+
     enum Section {
         SECTION_TOPLEVEL,
         SECTION_DECODERS,
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index 3629c8b..7b8f59d 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -25,6 +25,7 @@
 
 class ALooper;
 class AMessage;
+struct AReplyToken;
 class IGraphicBufferProducer;
 class MediaCodec;
 class MetaData;
@@ -85,8 +86,6 @@
     status_t initEncoder();
     void releaseEncoder();
     status_t feedEncoderInputBuffers();
-    void scheduleDoMoreWork();
-    status_t doMoreWork(int32_t numInput, int32_t numOutput);
     void suspend();
     void resume(int64_t skipFramesBeforeUs = -1ll);
     void signalEOS(status_t err = ERROR_END_OF_STREAM);
@@ -101,15 +100,13 @@
     sp<Puller> mPuller;
     sp<MediaCodec> mEncoder;
     uint32_t mFlags;
-    List<uint32_t> mStopReplyIDQueue;
+    List<sp<AReplyToken>> mStopReplyIDQueue;
     bool mIsVideo;
     bool mStarted;
     bool mStopping;
     bool mDoMoreWorkPending;
     sp<AMessage> mEncoderActivityNotify;
     sp<IGraphicBufferProducer> mGraphicBufferProducer;
-    Vector<sp<ABuffer> > mEncoderInputBuffers;
-    Vector<sp<ABuffer> > mEncoderOutputBuffers;
     List<MediaBuffer *> mInputBufferQueue;
     List<size_t> mAvailEncoderInputIndices;
     List<int64_t> mDecodingTimeQueue; // decoding time (us) for video
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index e67d4d5..a0036e0 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -36,6 +36,7 @@
 extern const char *MEDIA_MIMETYPE_AUDIO_MPEG;           // layer III
 extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I;
 extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II;
+extern const char *MEDIA_MIMETYPE_AUDIO_MIDI;
 extern const char *MEDIA_MIMETYPE_AUDIO_AAC;
 extern const char *MEDIA_MIMETYPE_AUDIO_QCELP;
 extern const char *MEDIA_MIMETYPE_AUDIO_VORBIS;
@@ -47,6 +48,7 @@
 extern const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS;
 extern const char *MEDIA_MIMETYPE_AUDIO_MSGSM;
 extern const char *MEDIA_MIMETYPE_AUDIO_AC3;
+extern const char *MEDIA_MIMETYPE_AUDIO_EAC3;
 
 extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
 extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
diff --git a/include/media/stagefright/MediaMuxer.h b/include/media/stagefright/MediaMuxer.h
index 9da98d9..e6538d1 100644
--- a/include/media/stagefright/MediaMuxer.h
+++ b/include/media/stagefright/MediaMuxer.h
@@ -50,9 +50,6 @@
         OUTPUT_FORMAT_LIST_END // must be last - used to validate format type
     };
 
-    // Construct the muxer with the output file path.
-    MediaMuxer(const char *path, OutputFormat format);
-
     // Construct the muxer with the file descriptor. Note that the MediaMuxer
     // will close this file at stop().
     MediaMuxer(int fd, OutputFormat format);
diff --git a/include/media/stagefright/ProcessInfo.h b/include/media/stagefright/ProcessInfo.h
new file mode 100644
index 0000000..ec0cdff
--- /dev/null
+++ b/include/media/stagefright/ProcessInfo.h
@@ -0,0 +1,40 @@
+/*
+ * 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 PROCESS_INFO_H_
+
+#define PROCESS_INFO_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/ProcessInfoInterface.h>
+
+namespace android {
+
+struct ProcessInfo : public ProcessInfoInterface {
+    ProcessInfo();
+
+    virtual bool getPriority(int pid, int* priority);
+
+protected:
+    virtual ~ProcessInfo();
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(ProcessInfo);
+};
+
+}  // namespace android
+
+#endif  // PROCESS_INFO_H_
diff --git a/services/audiopolicy/AudioPolicyFactory.cpp b/include/media/stagefright/ProcessInfoInterface.h
similarity index 60%
copy from services/audiopolicy/AudioPolicyFactory.cpp
copy to include/media/stagefright/ProcessInfoInterface.h
index 2ae7bc1..222f92d 100644
--- a/services/audiopolicy/AudioPolicyFactory.cpp
+++ b/include/media/stagefright/ProcessInfoInterface.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,19 +14,20 @@
  * limitations under the License.
  */
 
-#include "AudioPolicyManager.h"
+#ifndef PROCESS_INFO_INTERFACE_H_
+#define PROCESS_INFO_INTERFACE_H_
+
+#include <utils/RefBase.h>
 
 namespace android {
 
-extern "C" AudioPolicyInterface* createAudioPolicyManager(
-        AudioPolicyClientInterface *clientInterface)
-{
-    return new AudioPolicyManager(clientInterface);
-}
+struct ProcessInfoInterface : public RefBase {
+    virtual bool getPriority(int pid, int* priority) = 0;
 
-extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
-{
-    delete interface;
-}
+protected:
+    virtual ~ProcessInfoInterface() {}
+};
 
-}; // namespace android
+}  // namespace android
+
+#endif  // PROCESS_INFO_INTERFACE_H_
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
index ffe4f4c..2177c00 100644
--- a/include/media/stagefright/SurfaceMediaSource.h
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -126,7 +126,7 @@
     // Implementation of the BufferQueue::ConsumerListener interface.  These
     // calls are used to notify the Surface of asynchronous events in the
     // BufferQueue.
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
 
     // Used as a hook to BufferQueue::disconnect()
     // This is called by the client side when it is done
diff --git a/include/media/stagefright/foundation/ABase.h b/include/media/stagefright/foundation/ABase.h
index 72e3d87..ef1e010 100644
--- a/include/media/stagefright/foundation/ABase.h
+++ b/include/media/stagefright/foundation/ABase.h
@@ -18,7 +18,9 @@
 
 #define A_BASE_H_
 
+#ifndef ARRAY_SIZE
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+#endif
 
 #define DISALLOW_EVIL_CONSTRUCTORS(name) \
     name(const name &); \
diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h
index 450dcfe..1d0e2cb 100644
--- a/include/media/stagefright/foundation/ADebug.h
+++ b/include/media/stagefright/foundation/ADebug.h
@@ -80,6 +80,36 @@
             __FILE__ ":" LITERAL_TO_STRING(__LINE__)            \
                 " Should not be here.");
 
+struct ADebug {
+    enum Level {
+        kDebugNone,             // no debug
+        kDebugLifeCycle,        // lifecycle events: creation/deletion
+        kDebugState,            // commands and events
+        kDebugConfig,           // configuration
+        kDebugInternalState,    // internal state changes
+        kDebugAll,              // all
+        kDebugMax = kDebugAll,
+
+    };
+
+    // parse the property or string to get the debug level for a component name
+    // string format is:
+    // <level>[:<glob>][,<level>[:<glob>]...]
+    // - <level> is 0-5 corresponding to ADebug::Level
+    // - <glob> is used to match component name case insensitively, if omitted, it
+    //   matches all components
+    // - string is read left-to-right, and the last matching level is returned, or
+    //   the def if no terms matched
+    static Level GetDebugLevelFromProperty(
+            const char *name, const char *propertyName, Level def = kDebugNone);
+    static Level GetDebugLevelFromString(
+            const char *name, const char *value, Level def = kDebugNone);
+
+    // remove redundant segments of a codec name, and return a newly allocated
+    // string suitable for debugging
+    static char *GetDebugName(const char *name);
+};
+
 }  // namespace android
 
 #endif  // A_DEBUG_H_
diff --git a/include/media/stagefright/foundation/AHandler.h b/include/media/stagefright/foundation/AHandler.h
index b008b54..fe02a86 100644
--- a/include/media/stagefright/foundation/AHandler.h
+++ b/include/media/stagefright/foundation/AHandler.h
@@ -19,6 +19,7 @@
 #define A_HANDLER_H_
 
 #include <media/stagefright/foundation/ALooper.h>
+#include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
 
 namespace android {
@@ -27,27 +28,49 @@
 
 struct AHandler : public RefBase {
     AHandler()
-        : mID(0) {
+        : mID(0),
+          mVerboseStats(false),
+          mMessageCounter(0) {
     }
 
     ALooper::handler_id id() const {
         return mID;
     }
 
-    sp<ALooper> looper();
+    sp<ALooper> looper() const {
+        return mLooper.promote();
+    }
+
+    wp<ALooper> getLooper() const {
+        return mLooper;
+    }
+
+    wp<AHandler> getHandler() const {
+        // allow getting a weak reference to a const handler
+        return const_cast<AHandler *>(this);
+    }
 
 protected:
     virtual void onMessageReceived(const sp<AMessage> &msg) = 0;
 
 private:
-    friend struct ALooperRoster;
+    friend struct AMessage;      // deliverMessage()
+    friend struct ALooperRoster; // setID()
 
     ALooper::handler_id mID;
+    wp<ALooper> mLooper;
 
-    void setID(ALooper::handler_id id) {
+    inline void setID(ALooper::handler_id id, wp<ALooper> looper) {
         mID = id;
+        mLooper = looper;
     }
 
+    bool mVerboseStats;
+    uint32_t mMessageCounter;
+    KeyedVector<uint32_t, uint32_t> mMessages;
+
+    void deliverMessage(const sp<AMessage> &msg);
+
     DISALLOW_EVIL_CONSTRUCTORS(AHandler);
 };
 
diff --git a/include/media/stagefright/foundation/ALooper.h b/include/media/stagefright/foundation/ALooper.h
index 70e0c5e..09c469b 100644
--- a/include/media/stagefright/foundation/ALooper.h
+++ b/include/media/stagefright/foundation/ALooper.h
@@ -30,6 +30,7 @@
 
 struct AHandler;
 struct AMessage;
+struct AReplyToken;
 
 struct ALooper : public RefBase {
     typedef int32_t event_id;
@@ -53,11 +54,15 @@
 
     static int64_t GetNowUs();
 
+    const char *getName() const {
+        return mName.c_str();
+    }
+
 protected:
     virtual ~ALooper();
 
 private:
-    friend struct ALooperRoster;
+    friend struct AMessage;       // post()
 
     struct Event {
         int64_t mWhenUs;
@@ -75,12 +80,32 @@
     sp<LooperThread> mThread;
     bool mRunningLocally;
 
+    // use a separate lock for reply handling, as it is always on another thread
+    // use a central lock, however, to avoid creating a mutex for each reply
+    Mutex mRepliesLock;
+    Condition mRepliesCondition;
+
+    // START --- methods used only by AMessage
+
+    // posts a message on this looper with the given timeout
     void post(const sp<AMessage> &msg, int64_t delayUs);
+
+    // creates a reply token to be used with this looper
+    sp<AReplyToken> createReplyToken();
+    // waits for a response for the reply token.  If status is OK, the response
+    // is stored into the supplied variable.  Otherwise, it is unchanged.
+    status_t awaitResponse(const sp<AReplyToken> &replyToken, sp<AMessage> *response);
+    // posts a reply for a reply token.  If the reply could be successfully posted,
+    // it returns OK. Otherwise, it returns an error value.
+    status_t postReply(const sp<AReplyToken> &replyToken, const sp<AMessage> &msg);
+
+    // END --- methods used only by AMessage
+
     bool loop();
 
     DISALLOW_EVIL_CONSTRUCTORS(ALooper);
 };
 
-}  // namespace android
+} // namespace android
 
 #endif  // A_LOOPER_H_
diff --git a/include/media/stagefright/foundation/ALooperRoster.h b/include/media/stagefright/foundation/ALooperRoster.h
index 4d76b64..9912455 100644
--- a/include/media/stagefright/foundation/ALooperRoster.h
+++ b/include/media/stagefright/foundation/ALooperRoster.h
@@ -20,6 +20,7 @@
 
 #include <media/stagefright/foundation/ALooper.h>
 #include <utils/KeyedVector.h>
+#include <utils/String16.h>
 
 namespace android {
 
@@ -32,15 +33,7 @@
     void unregisterHandler(ALooper::handler_id handlerID);
     void unregisterStaleHandlers();
 
-    status_t postMessage(const sp<AMessage> &msg, int64_t delayUs = 0);
-    void deliverMessage(const sp<AMessage> &msg);
-
-    status_t postAndAwaitResponse(
-            const sp<AMessage> &msg, sp<AMessage> *response);
-
-    void postReply(uint32_t replyID, const sp<AMessage> &reply);
-
-    sp<ALooper> findLooper(ALooper::handler_id handlerID);
+    void dump(int fd, const Vector<String16>& args);
 
 private:
     struct HandlerInfo {
@@ -51,10 +44,6 @@
     Mutex mLock;
     KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers;
     ALooper::handler_id mNextHandlerID;
-    uint32_t mNextReplyID;
-    Condition mRepliesCondition;
-
-    KeyedVector<uint32_t, sp<AMessage> > mReplies;
 
     DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster);
 };
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
index a9e235b..4c6bd21 100644
--- a/include/media/stagefright/foundation/AMessage.h
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -26,11 +26,41 @@
 namespace android {
 
 struct ABuffer;
+struct AHandler;
 struct AString;
 struct Parcel;
 
+struct AReplyToken : public RefBase {
+    AReplyToken(const sp<ALooper> &looper)
+        : mLooper(looper),
+          mReplied(false) {
+    }
+
+private:
+    friend struct AMessage;
+    friend struct ALooper;
+    wp<ALooper> mLooper;
+    sp<AMessage> mReply;
+    bool mReplied;
+
+    sp<ALooper> getLooper() const {
+        return mLooper.promote();
+    }
+    // if reply is not set, returns false; otherwise, it retrieves the reply and returns true
+    bool retrieveReply(sp<AMessage> *reply) {
+        if (mReplied) {
+            *reply = mReply;
+            mReply.clear();
+        }
+        return mReplied;
+    }
+    // sets the reply for this token. returns OK or error
+    status_t setReply(const sp<AMessage> &reply);
+};
+
 struct AMessage : public RefBase {
-    AMessage(uint32_t what = 0, ALooper::handler_id target = 0);
+    AMessage();
+    AMessage(uint32_t what, const sp<const AHandler> &handler);
 
     static sp<AMessage> FromParcel(const Parcel &parcel);
     void writeToParcel(Parcel *parcel) const;
@@ -38,8 +68,7 @@
     void setWhat(uint32_t what);
     uint32_t what() const;
 
-    void setTarget(ALooper::handler_id target);
-    ALooper::handler_id target() const;
+    void setTarget(const sp<const AHandler> &handler);
 
     void clear();
 
@@ -76,18 +105,22 @@
             const char *name,
             int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const;
 
-    void post(int64_t delayUs = 0);
+    status_t post(int64_t delayUs = 0);
 
     // Posts the message to its target and waits for a response (or error)
     // before returning.
     status_t postAndAwaitResponse(sp<AMessage> *response);
 
     // If this returns true, the sender of this message is synchronously
-    // awaiting a response, the "replyID" can be used to send the response
-    // via "postReply" below.
-    bool senderAwaitsResponse(uint32_t *replyID) const;
+    // awaiting a response and the reply token is consumed from the message
+    // and stored into replyID. The reply token must be used to send the response
+    // using "postReply" below.
+    bool senderAwaitsResponse(sp<AReplyToken> *replyID);
 
-    void postReply(uint32_t replyID);
+    // Posts the message as a response to a reply token.  A reply token can
+    // only be used once. Returns OK if the response could be posted; otherwise,
+    // an error.
+    status_t postReply(const sp<AReplyToken> &replyID);
 
     // Performs a deep-copy of "this", contained messages are in turn "dup'ed".
     // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
@@ -117,9 +150,16 @@
     virtual ~AMessage();
 
 private:
+    friend struct ALooper; // deliver()
+
     uint32_t mWhat;
+
+    // used only for debugging
     ALooper::handler_id mTarget;
 
+    wp<AHandler> mHandler;
+    wp<ALooper> mLooper;
+
     struct Rect {
         int32_t mLeft, mTop, mRight, mBottom;
     };
@@ -157,6 +197,8 @@
 
     size_t findItemIndex(const char *name, size_t len) const;
 
+    void deliver();
+
     DISALLOW_EVIL_CONSTRUCTORS(AMessage);
 };
 
diff --git a/include/media/stagefright/foundation/AString.h b/include/media/stagefright/foundation/AString.h
index 7c98699..822dbb3 100644
--- a/include/media/stagefright/foundation/AString.h
+++ b/include/media/stagefright/foundation/AString.h
@@ -23,7 +23,7 @@
 
 namespace android {
 
-struct String8;
+class String8;
 struct Parcel;
 
 struct AString {
@@ -102,7 +102,7 @@
     void makeMutable();
 };
 
-AString StringPrintf(const char *format, ...);
+AString AStringPrintf(const char *format, ...);
 
 }  // namespace android
 
diff --git a/include/media/stagefright/foundation/AStringUtils.h b/include/media/stagefright/foundation/AStringUtils.h
new file mode 100644
index 0000000..76a7791
--- /dev/null
+++ b/include/media/stagefright/foundation/AStringUtils.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014 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 A_STRING_UTILS_H_
+#define A_STRING_UTILS_H_
+
+#include <stdlib.h>
+
+namespace android {
+
+struct AStringUtils {
+    // similar to strncmp or strcasecmp, but case sensitivity is parametric
+    static int Compare(const char *a, const char *b, size_t len, bool ignoreCase);
+
+    // matches a string (str) to a glob pattern that supports:
+    //    * - matches any number of characters
+    static bool MatchesGlob(
+            const char *glob, size_t globLen, const char *str, size_t strLen, bool ignoreCase);
+};
+
+}  // namespace android
+
+#endif  // A_STRING_UTILS_H_
diff --git a/include/media/stagefright/foundation/AUtils.h b/include/media/stagefright/foundation/AUtils.h
index 3a73a39..d7ecf50 100644
--- a/include/media/stagefright/foundation/AUtils.h
+++ b/include/media/stagefright/foundation/AUtils.h
@@ -40,6 +40,12 @@
     }
 }
 
+/* == ceil(nom / den) * den. T must be integer type, alignment must be positive power of 2 */
+template<class T, class U>
+inline static const T align(const T &nom, const U &den) {
+    return (nom + (T)(den - 1)) & (T)~(den - 1);
+}
+
 template<class T>
 inline static T abs(const T &a) {
     return a < 0 ? -a : a;
diff --git a/include/media/stagefright/foundation/AWakeLock.h b/include/media/stagefright/foundation/AWakeLock.h
new file mode 100644
index 0000000..57716c1
--- /dev/null
+++ b/include/media/stagefright/foundation/AWakeLock.h
@@ -0,0 +1,68 @@
+/*
+ * 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 A_WAKELOCK_H_
+#define A_WAKELOCK_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <powermanager/IPowerManager.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class AWakeLock : public RefBase {
+
+public:
+    AWakeLock();
+
+    // NOTE: acquire and release are not thread safe
+
+    // returns true if wakelock was acquired
+    bool acquire();
+    void release(bool force = false);
+
+    virtual ~AWakeLock();
+
+private:
+    sp<IPowerManager> mPowerManager;
+    sp<IBinder>       mWakeLockToken;
+    uint32_t          mWakeLockCount;
+
+    class PMDeathRecipient : public IBinder::DeathRecipient {
+    public:
+        PMDeathRecipient(AWakeLock *wakeLock) : mWakeLock(wakeLock) {}
+        virtual ~PMDeathRecipient() {}
+
+        // IBinder::DeathRecipient
+        virtual void binderDied(const wp<IBinder> &who);
+
+    private:
+        PMDeathRecipient(const PMDeathRecipient&);
+        PMDeathRecipient& operator= (const PMDeathRecipient&);
+
+        AWakeLock *mWakeLock;
+    };
+
+    const sp<PMDeathRecipient> mDeathRecipient;
+
+    void clearPowerManager();
+
+    DISALLOW_EVIL_CONSTRUCTORS(AWakeLock);
+};
+
+}  // namespace android
+
+#endif  // A_WAKELOCK_H_
diff --git a/include/ndk/NdkMediaCodec.h b/include/ndk/NdkMediaCodec.h
index c07f4c9..4f6a1ef 100644
--- a/include/ndk/NdkMediaCodec.h
+++ b/include/ndk/NdkMediaCodec.h
@@ -142,7 +142,8 @@
 /**
  * Get the index of the next available buffer of processed data.
  */
-ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec*, AMediaCodecBufferInfo *info, int64_t timeoutUs);
+ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec*, AMediaCodecBufferInfo *info,
+        int64_t timeoutUs);
 AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec*);
 
 /**
diff --git a/include/ndk/NdkMediaDrm.h b/include/ndk/NdkMediaDrm.h
index 10afdd9..3c312a9 100644
--- a/include/ndk/NdkMediaDrm.h
+++ b/include/ndk/NdkMediaDrm.h
@@ -327,24 +327,24 @@
 /**
  * String property name: identifies the maker of the DRM engine plugin
  */
-const char *PROPERTY_VENDOR = "vendor";
+#define PROPERTY_VENDOR "vendor"
 
 /**
  * String property name: identifies the version of the DRM engine plugin
  */
-const char *PROPERTY_VERSION = "version";
+#define PROPERTY_VERSION "version"
 
 /**
  * String property name: describes the DRM engine plugin
  */
-const char *PROPERTY_DESCRIPTION = "description";
+#define PROPERTY_DESCRIPTION "description"
 
 /**
  * String property name: a comma-separated list of cipher and mac algorithms
  * supported by CryptoSession.  The list may be empty if the DRM engine
  * plugin does not support CryptoSession operations.
  */
-const char *PROPERTY_ALGORITHMS = "algorithms";
+#define PROPERTY_ALGORITHMS "algorithms"
 
 /**
  * Read a DRM engine plugin String property value, given the property name string.
@@ -361,7 +361,7 @@
  * Byte array property name: the device unique identifier is established during
  * device provisioning and provides a means of uniquely identifying each device.
  */
-const char *PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId";
+#define PROPERTY_DEVICE_UNIQUE_ID "deviceUniqueId"
 
 /**
  * Read a DRM engine plugin byte array property value, given the property name string.
diff --git a/include/ndk/NdkMediaExtractor.h b/include/ndk/NdkMediaExtractor.h
index 7a4e702..7324d31 100644
--- a/include/ndk/NdkMediaExtractor.h
+++ b/include/ndk/NdkMediaExtractor.h
@@ -55,12 +55,14 @@
 /**
  *  Set the file descriptor from which the extractor will read.
  */
-media_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor*, int fd, off64_t offset, off64_t length);
+media_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor*, int fd, off64_t offset,
+        off64_t length);
 
 /**
  * Set the URI from which the extractor will read.
  */
-media_status_t AMediaExtractor_setDataSource(AMediaExtractor*, const char *location); // TODO support headers
+media_status_t AMediaExtractor_setDataSource(AMediaExtractor*, const char *location);
+        // TODO support headers
 
 /**
  * Return the number of tracks in the previously specified media file
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index fa1b20a..5644428 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -24,9 +24,8 @@
 #include <utils/threads.h>
 #include <utils/Log.h>
 #include <utils/RefBase.h>
-#include <media/nbaio/roundup.h>
+#include <audio_utils/roundup.h>
 #include <media/SingleStateQueue.h>
-#include <private/media/StaticAudioTrackState.h>
 
 namespace android {
 
@@ -54,22 +53,64 @@
 struct AudioTrackSharedStreaming {
     // similar to NBAIO MonoPipe
     // in continuously incrementing frame units, take modulo buffer size, which must be a power of 2
-    volatile int32_t mFront;    // read by server
-    volatile int32_t mRear;     // write by client
+    volatile int32_t mFront;    // read by consumer (output: server, input: client)
+    volatile int32_t mRear;     // written by producer (output: client, input: server)
     volatile int32_t mFlush;    // incremented by client to indicate a request to flush;
                                 // server notices and discards all data between mFront and mRear
     volatile uint32_t mUnderrunFrames;  // server increments for each unavailable but desired frame
 };
 
+// Represents a single state of an AudioTrack that was created in static mode (shared memory buffer
+// supplied by the client).  This state needs to be communicated from the client to server.  As this
+// state is too large to be updated atomically without a mutex, and mutexes aren't allowed here, the
+// state is wrapped by a SingleStateQueue.
+struct StaticAudioTrackState {
+    // Do not define constructors, destructors, or virtual methods as this is part of a
+    // union in shared memory and they will not get called properly.
+
+    // These fields should both be size_t, but since they are located in shared memory we
+    // force to 32-bit.  The client and server may have different typedefs for size_t.
+
+    // The state has a sequence counter to indicate whether changes are made to loop or position.
+    // The sequence counter also currently indicates whether loop or position is first depending
+    // on which is greater; it jumps by max(mLoopSequence, mPositionSequence) + 1.
+
+    uint32_t    mLoopStart;
+    uint32_t    mLoopEnd;
+    int32_t     mLoopCount;
+    uint32_t    mLoopSequence; // a sequence counter to indicate changes to loop
+    uint32_t    mPosition;
+    uint32_t    mPositionSequence; // a sequence counter to indicate changes to position
+};
+
 typedef SingleStateQueue<StaticAudioTrackState> StaticAudioTrackSingleStateQueue;
 
+struct StaticAudioTrackPosLoop {
+    // Do not define constructors, destructors, or virtual methods as this is part of a
+    // union in shared memory and will not get called properly.
+
+    // These fields should both be size_t, but since they are located in shared memory we
+    // force to 32-bit.  The client and server may have different typedefs for size_t.
+
+    // This struct information is stored in a single state queue to communicate the
+    // static AudioTrack server state to the client while data is consumed.
+    // It is smaller than StaticAudioTrackState to prevent unnecessary information from
+    // being sent.
+
+    uint32_t mBufferPosition;
+    int32_t  mLoopCount;
+};
+
+typedef SingleStateQueue<StaticAudioTrackPosLoop> StaticAudioTrackPosLoopQueue;
+
 struct AudioTrackSharedStatic {
+    // client requests to the server for loop or position changes.
     StaticAudioTrackSingleStateQueue::Shared
                     mSingleStateQueue;
-    // This field should be a size_t, but since it is located in shared memory we
-    // force to 32-bit.  The client and server may have different typedefs for size_t.
-    uint32_t        mBufferPosition;    // updated asynchronously by server,
-                                        // "for entertainment purposes only"
+    // position info updated asynchronously by server and read by client,
+    // "for entertainment purposes only"
+    StaticAudioTrackPosLoopQueue::Shared
+                    mPosLoopQueue;
 };
 
 // ----------------------------------------------------------------------------
@@ -96,7 +137,8 @@
                 uint32_t    mServer;    // Number of filled frames consumed by server (mIsOut),
                                         // or filled frames provided by server (!mIsOut).
                                         // It is updated asynchronously by server without a barrier.
-                                        // The value should be used "for entertainment purposes only",
+                                        // The value should be used
+                                        // "for entertainment purposes only",
                                         // which means don't make important decisions based on it.
 
                 uint32_t    mPad1;      // unused
@@ -313,8 +355,28 @@
     virtual void    flush();
 
 #define MIN_LOOP    16  // minimum length of each loop iteration in frames
+
+            // setLoop(), setBufferPosition(), and setBufferPositionAndLoop() set the
+            // static buffer position and looping parameters.  These commands are not
+            // synchronous (they do not wait or block); instead they take effect at the
+            // next buffer data read from the server side. However, the client side
+            // getters will read a cached version of the position and loop variables
+            // until the setting takes effect.
+            //
+            // setBufferPositionAndLoop() is equivalent to calling, in order, setLoop() and
+            // setBufferPosition().
+            //
+            // The functions should not be relied upon to do parameter or state checking.
+            // That is done at the AudioTrack level.
+
             void    setLoop(size_t loopStart, size_t loopEnd, int loopCount);
+            void    setBufferPosition(size_t position);
+            void    setBufferPositionAndLoop(size_t position, size_t loopStart, size_t loopEnd,
+                                             int loopCount);
             size_t  getBufferPosition();
+                    // getBufferPositionAndLoopCount() provides the proper snapshot of
+                    // position and loopCount together.
+            void    getBufferPositionAndLoopCount(size_t *position, int *loopCount);
 
     virtual size_t  getMisalignment() {
         return 0;
@@ -326,7 +388,9 @@
 
 private:
     StaticAudioTrackSingleStateQueue::Mutator   mMutator;
-    size_t          mBufferPosition;    // so that getBufferPosition() appears to be synchronous
+    StaticAudioTrackPosLoopQueue::Observer      mPosLoopObserver;
+                        StaticAudioTrackState   mState;   // last communicated state to server
+                        StaticAudioTrackPosLoop mPosLoop; // snapshot of position and loop.
 };
 
 // ----------------------------------------------------------------------------
@@ -447,12 +511,23 @@
     virtual uint32_t    getUnderrunFrames() const { return 0; }
 
 private:
+    status_t            updateStateWithLoop(StaticAudioTrackState *localState,
+                                            const StaticAudioTrackState &update) const;
+    status_t            updateStateWithPosition(StaticAudioTrackState *localState,
+                                                const StaticAudioTrackState &update) const;
     ssize_t             pollPosition(); // poll for state queue update, and return current position
     StaticAudioTrackSingleStateQueue::Observer  mObserver;
-    size_t              mPosition;  // server's current play position in frames, relative to 0
-    size_t              mEnd;       // cached value computed from mState, safe for asynchronous read
+    StaticAudioTrackPosLoopQueue::Mutator       mPosLoopMutator;
+    size_t              mFramesReadySafe; // Assuming size_t read/writes are atomic on 32 / 64 bit
+                                          // processors, this is a thread-safe version of
+                                          // mFramesReady.
+    int64_t             mFramesReady;     // The number of frames ready in the static buffer
+                                          // including loops.  This is 64 bits since loop mode
+                                          // can cause a track to appear to have a large number
+                                          // of frames. INT64_MAX means an infinite loop.
     bool                mFramesReadyIsCalledByMultipleThreads;
-    StaticAudioTrackState   mState;
+    StaticAudioTrackState mState;         // Server side state. Any updates from client must be
+                                          // passed by the mObserver SingleStateQueue.
 };
 
 // Proxy used by AudioFlinger for servicing AudioRecord
diff --git a/include/private/media/StaticAudioTrackState.h b/include/private/media/StaticAudioTrackState.h
deleted file mode 100644
index d483061..0000000
--- a/include/private/media/StaticAudioTrackState.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2012 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 STATIC_AUDIO_TRACK_STATE_H
-#define STATIC_AUDIO_TRACK_STATE_H
-
-namespace android {
-
-// Represents a single state of an AudioTrack that was created in static mode (shared memory buffer
-// supplied by the client).  This state needs to be communicated from the client to server.  As this
-// state is too large to be updated atomically without a mutex, and mutexes aren't allowed here, the
-// state is wrapped by a SingleStateQueue.
-struct StaticAudioTrackState {
-    // do not define constructors, destructors, or virtual methods
-
-    // These fields should both be size_t, but since they are located in shared memory we
-    // force to 32-bit.  The client and server may have different typedefs for size_t.
-    uint32_t    mLoopStart;
-    uint32_t    mLoopEnd;
-
-    int         mLoopCount;
-};
-
-}   // namespace android
-
-#endif  // STATIC_AUDIO_TRACK_STATE_H
diff --git a/include/radio/IRadio.h b/include/radio/IRadio.h
new file mode 100644
index 0000000..1877f8f
--- /dev/null
+++ b/include/radio/IRadio.h
@@ -0,0 +1,70 @@
+/*
+ * 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_HARDWARE_IRADIO_H
+#define ANDROID_HARDWARE_IRADIO_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <system/radio.h>
+
+namespace android {
+
+class IRadio : public IInterface
+{
+public:
+
+    DECLARE_META_INTERFACE(Radio);
+
+    virtual void detach() = 0;
+
+    virtual status_t setConfiguration(const struct radio_band_config *config) = 0;
+
+    virtual status_t getConfiguration(struct radio_band_config *config) = 0;
+
+    virtual status_t setMute(bool mute) = 0;
+
+    virtual status_t getMute(bool *mute) = 0;
+
+    virtual status_t step(radio_direction_t direction, bool skipSubChannel) = 0;
+
+    virtual status_t scan(radio_direction_t direction, bool skipSubChannel) = 0;
+
+    virtual status_t tune(unsigned int channel, unsigned int subChannel) = 0;
+
+    virtual status_t cancel() = 0;
+
+    virtual status_t getProgramInformation(struct radio_program_info *info) = 0;
+
+    virtual status_t hasControl(bool *hasControl) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnRadio: public BnInterface<IRadio>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_IRADIO_H
diff --git a/include/radio/IRadioClient.h b/include/radio/IRadioClient.h
new file mode 100644
index 0000000..9062ad6
--- /dev/null
+++ b/include/radio/IRadioClient.h
@@ -0,0 +1,50 @@
+/*
+ * 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_HARDWARE_IRADIO_CLIENT_H
+#define ANDROID_HARDWARE_IRADIO_CLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IRadioClient : public IInterface
+{
+public:
+
+    DECLARE_META_INTERFACE(RadioClient);
+
+    virtual void onEvent(const sp<IMemory>& eventMemory) = 0;
+
+};
+
+// ----------------------------------------------------------------------------
+
+class BnRadioClient : public BnInterface<IRadioClient>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_IRADIO_CLIENT_H
diff --git a/include/radio/IRadioService.h b/include/radio/IRadioService.h
new file mode 100644
index 0000000..a946dd5
--- /dev/null
+++ b/include/radio/IRadioService.h
@@ -0,0 +1,59 @@
+/*
+ * 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_HARDWARE_IRADIO_SERVICE_H
+#define ANDROID_HARDWARE_IRADIO_SERVICE_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <system/radio.h>
+
+namespace android {
+
+class IRadio;
+class IRadioClient;
+
+class IRadioService : public IInterface
+{
+public:
+
+    DECLARE_META_INTERFACE(RadioService);
+
+    virtual status_t listModules(struct radio_properties *properties,
+                                 uint32_t *numModules) = 0;
+
+    virtual status_t attach(const radio_handle_t handle,
+                            const sp<IRadioClient>& client,
+                            const struct radio_band_config *config,
+                            bool withAudio,
+                            sp<IRadio>& radio) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnRadioService: public BnInterface<IRadioService>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_IRADIO_SERVICE_H
diff --git a/include/radio/Radio.h b/include/radio/Radio.h
new file mode 100644
index 0000000..302bf16
--- /dev/null
+++ b/include/radio/Radio.h
@@ -0,0 +1,88 @@
+/*
+ * 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_HARDWARE_RADIO_H
+#define ANDROID_HARDWARE_RADIO_H
+
+#include <binder/IBinder.h>
+#include <utils/threads.h>
+#include <radio/RadioCallback.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioService.h>
+#include <radio/IRadioClient.h>
+#include <system/radio.h>
+
+namespace android {
+
+class MemoryDealer;
+
+class Radio : public BnRadioClient,
+                        public IBinder::DeathRecipient
+{
+public:
+
+    virtual ~Radio();
+
+    static  status_t listModules(struct radio_properties *properties,
+                                 uint32_t *numModules);
+    static  sp<Radio> attach(radio_handle_t handle,
+                             const struct radio_band_config *config,
+                             bool withAudio,
+                             const sp<RadioCallback>& callback);
+
+
+            void detach();
+
+            status_t setConfiguration(const struct radio_band_config *config);
+
+            status_t getConfiguration(struct radio_band_config *config);
+
+            status_t setMute(bool mute);
+
+            status_t getMute(bool *mute);
+
+            status_t step(radio_direction_t direction, bool skipSubChannel);
+
+            status_t scan(radio_direction_t direction, bool skipSubChannel);
+
+            status_t tune(unsigned int channel, unsigned int subChannel);
+
+            status_t cancel();
+
+            status_t getProgramInformation(struct radio_program_info *info);
+
+            status_t hasControl(bool *hasControl);
+
+            // BpRadioClient
+            virtual void onEvent(const sp<IMemory>& eventMemory);
+
+            //IBinder::DeathRecipient
+            virtual void binderDied(const wp<IBinder>& who);
+
+private:
+            Radio(radio_handle_t handle,
+                            const sp<RadioCallback>&);
+            static const sp<IRadioService>& getRadioService();
+
+            Mutex                   mLock;
+            sp<IRadio>              mIRadio;
+            const radio_handle_t    mHandle;
+            sp<RadioCallback>       mCallback;
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_RADIO_H
diff --git a/include/radio/RadioCallback.h b/include/radio/RadioCallback.h
new file mode 100644
index 0000000..4a7f1a6
--- /dev/null
+++ b/include/radio/RadioCallback.h
@@ -0,0 +1,38 @@
+/*
+ * 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_HARDWARE_RADIO_CALLBACK_H
+#define ANDROID_HARDWARE_RADIO_CALLBACK_H
+
+#include <utils/RefBase.h>
+#include <system/radio.h>
+
+namespace android {
+
+class RadioCallback : public RefBase
+{
+public:
+
+            RadioCallback() {}
+    virtual ~RadioCallback() {}
+
+    virtual void onEvent(struct radio_event *event) = 0;
+
+};
+
+}; // namespace android
+
+#endif //ANDROID_HARDWARE_RADIO_CALLBACK_H
diff --git a/media/common_time/ICommonClock.cpp b/media/common_time/ICommonClock.cpp
index 25ae69e..19b7d6e 100644
--- a/media/common_time/ICommonClock.cpp
+++ b/media/common_time/ICommonClock.cpp
@@ -206,7 +206,7 @@
             const sp<ICommonClockListener>& listener) {
         Parcel data, reply;
         data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
-        data.writeStrongBinder(listener->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(listener));
 
         status_t status = remote()->transact(REGISTER_LISTENER, data, &reply);
 
@@ -221,7 +221,7 @@
             const sp<ICommonClockListener>& listener) {
         Parcel data, reply;
         data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
-        data.writeStrongBinder(listener->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(listener));
         status_t status = remote()->transact(UNREGISTER_LISTENER, data, &reply);
 
         if (status == OK) {
diff --git a/media/img_utils/include/img_utils/TiffEntryImpl.h b/media/img_utils/include/img_utils/TiffEntryImpl.h
index f5ccb5e..c73e231 100644
--- a/media/img_utils/include/img_utils/TiffEntryImpl.h
+++ b/media/img_utils/include/img_utils/TiffEntryImpl.h
@@ -147,7 +147,7 @@
 }
 
 template<typename T>
-status_t TiffEntryImpl<T>::writeData(uint32_t offset, EndianOutput* out) const {
+status_t TiffEntryImpl<T>::writeData(uint32_t /*offset*/, EndianOutput* out) const {
     status_t ret = OK;
 
     // Some tags have fixed-endian value output
diff --git a/media/img_utils/src/FileInput.cpp b/media/img_utils/src/FileInput.cpp
index 498e715..4c85a51 100644
--- a/media/img_utils/src/FileInput.cpp
+++ b/media/img_utils/src/FileInput.cpp
@@ -78,7 +78,7 @@
         ret = BAD_VALUE;
     }
     mOpen = false;
-    return OK;
+    return ret;
 }
 
 } /*namespace img_utils*/
diff --git a/media/img_utils/src/FileOutput.cpp b/media/img_utils/src/FileOutput.cpp
index ce763ff..0346762 100644
--- a/media/img_utils/src/FileOutput.cpp
+++ b/media/img_utils/src/FileOutput.cpp
@@ -72,7 +72,7 @@
         ret = BAD_VALUE;
     }
     mOpen = false;
-    return OK;
+    return ret;
 }
 
 } /*namespace img_utils*/
diff --git a/media/img_utils/src/TiffWriter.cpp b/media/img_utils/src/TiffWriter.cpp
index ac41734..a6f9218 100644
--- a/media/img_utils/src/TiffWriter.cpp
+++ b/media/img_utils/src/TiffWriter.cpp
@@ -106,7 +106,6 @@
 
     for (size_t i = 0; i < offVecSize; ++i) {
         uint32_t ifdKey = offsetVector.keyAt(i);
-        uint32_t nextOffset = offsetVector[i];
         uint32_t sizeToWrite = mNamedIfds[ifdKey]->getStripSize();
         bool found = false;
         for (size_t j = 0; j < sourcesCount; ++j) {
@@ -124,7 +123,7 @@
             ALOGE("%s: No stream for byte strips for IFD %u", __FUNCTION__, ifdKey);
             return BAD_VALUE;
         }
-        assert(nextOffset == endOut.getCurrentOffset());
+        assert(offsetVector[i] == endOut.getCurrentOffset());
     }
 
     return ret;
diff --git a/media/libcpustats/ThreadCpuUsage.cpp b/media/libcpustats/ThreadCpuUsage.cpp
index cfdcb51..b43b36c 100644
--- a/media/libcpustats/ThreadCpuUsage.cpp
+++ b/media/libcpustats/ThreadCpuUsage.cpp
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include <stdlib.h>
+#include <string.h>
 #include <time.h>
 
 #include <utils/Log.h>
@@ -74,7 +75,6 @@
 
 bool ThreadCpuUsage::sampleAndEnable(double& ns)
 {
-    bool ret;
     bool wasEverEnabled = mWasEverEnabled;
     if (enable()) {
         // already enabled, so add a new sample relative to previous
diff --git a/media/libeffects/loudness/Android.mk b/media/libeffects/loudness/Android.mk
index 70d7984..55d0611 100644
--- a/media/libeffects/loudness/Android.mk
+++ b/media/libeffects/loudness/Android.mk
@@ -19,5 +19,4 @@
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, audio-effects) \
 
-include external/stlport/libstlport.mk
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 6c2cbe3..6aeb919 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -766,6 +766,122 @@
     return 0;
 }    /* end LvmBundle_process */
 
+
+//----------------------------------------------------------------------------
+// EqualizerUpdateActiveParams()
+//----------------------------------------------------------------------------
+// Purpose: Update ActiveParams for Equalizer
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+void EqualizerUpdateActiveParams(EffectContext *pContext) {
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerUpdateActiveParams")
+    //ALOGV("\tEqualizerUpdateActiveParams Succesfully returned from LVM_GetControlParameters\n");
+    //ALOGV("\tEqualizerUpdateActiveParams just Got -> %d\n",
+    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+
+    for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+           ActiveParams.pEQNB_BandDefinition[i].Frequency = EQNB_5BandPresetsFrequencies[i];
+           ActiveParams.pEQNB_BandDefinition[i].QFactor   = EQNB_5BandPresetsQFactors[i];
+           ActiveParams.pEQNB_BandDefinition[i].Gain = pContext->pBundledContext->bandGaindB[i];
+       }
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "EqualizerUpdateActiveParams")
+    //ALOGV("\tEqualizerUpdateActiveParams just Set -> %d\n",
+    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+}
+
+//----------------------------------------------------------------------------
+// LvmEffect_limitLevel()
+//----------------------------------------------------------------------------
+// Purpose: limit the overall level to a value less than 0 dB preserving
+//          the overall EQ band gain and BassBoost relative levels.
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+void LvmEffect_limitLevel(EffectContext *pContext) {
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "LvmEffect_limitLevel")
+    //ALOGV("\tLvmEffect_limitLevel Succesfully returned from LVM_GetControlParameters\n");
+    //ALOGV("\tLvmEffect_limitLevel just Got -> %d\n",
+    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+    int gainCorrection = 0;
+    //Count the energy contribution per band for EQ and BassBoost only if they are active.
+    float energyContribution = 0;
+
+    //EQ contribution
+    if (pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE) {
+        for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+            float bandEnergy = (pContext->pBundledContext->bandGaindB[i] *
+                    LimitLevel_bandEnergyContribution[i])/15.0;
+            if (bandEnergy > 0)
+                energyContribution += bandEnergy;
+        }
+    }
+
+    //BassBoost contribution
+    if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
+        float bandEnergy = (pContext->pBundledContext->BassStrengthSaved *
+                LimitLevel_bassBoostEnergyContribution)/1000.0;
+        if (bandEnergy > 0)
+            energyContribution += bandEnergy;
+    }
+
+    //Virtualizer contribution
+    if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
+                   energyContribution += LimitLevel_virtualizerContribution;
+        }
+
+    //roundoff
+    int maxLevelRound = (int)(energyContribution + 0.99);
+    if (maxLevelRound + pContext->pBundledContext->volume > 0) {
+        gainCorrection = maxLevelRound + pContext->pBundledContext->volume;
+    }
+
+    ActiveParams.VC_EffectLevel  = pContext->pBundledContext->volume - gainCorrection;
+    if (ActiveParams.VC_EffectLevel < -96) {
+        ActiveParams.VC_EffectLevel = -96;
+    }
+    ALOGV("\tVol:%d, GainCorrection: %d, Actual vol: %d", pContext->pBundledContext->volume,
+            gainCorrection, ActiveParams.VC_EffectLevel);
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmEffect_limitLevel")
+    //ALOGV("\tLvmEffect_limitLevel just Set -> %d\n",
+    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+    //ALOGV("\tLvmEffect_limitLevel just set (-96dB -> 0dB) -> %d\n",ActiveParams.VC_EffectLevel );
+    if (pContext->pBundledContext->firstVolume == LVM_TRUE){
+        LvmStatus = LVM_SetVolumeNoSmoothing(pContext->pBundledContext->hInstance, &ActiveParams);
+        LVM_ERROR_CHECK(LvmStatus, "LVM_SetVolumeNoSmoothing", "LvmBundle_process")
+        ALOGV("\tLVM_VOLUME: Disabling Smoothing for first volume change to remove spikes/clicks");
+        pContext->pBundledContext->firstVolume = LVM_FALSE;
+    }
+}
+
 //----------------------------------------------------------------------------
 // LvmEffect_enable()
 //----------------------------------------------------------------------------
@@ -814,6 +930,7 @@
 
     //ALOGV("\tLvmEffect_enable Succesfully called LVM_SetControlParameters\n");
     //ALOGV("\tLvmEffect_enable end");
+    LvmEffect_limitLevel(pContext);
     return 0;
 }
 
@@ -864,6 +981,7 @@
 
     //ALOGV("\tLvmEffect_disable Succesfully called LVM_SetControlParameters\n");
     //ALOGV("\tLvmEffect_disable end");
+    LvmEffect_limitLevel(pContext);
     return 0;
 }
 
@@ -1099,6 +1217,8 @@
 
     LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "BassSetStrength")
     //ALOGV("\tBassSetStrength Succesfully called LVM_SetControlParameters\n");
+
+    LvmEffect_limitLevel(pContext);
 }    /* end BassSetStrength */
 
 //----------------------------------------------------------------------------
@@ -1159,13 +1279,14 @@
     /* Virtualizer parameters */
     ActiveParams.CS_EffectLevel             = (int)((strength*32767)/1000);
 
-    //ALOGV("\tVirtualizerSetStrength() (0-1000)   -> %d\n", strength );
-    //ALOGV("\tVirtualizerSetStrength() (0- 100)   -> %d\n", ActiveParams.CS_EffectLevel );
+    ALOGV("\tVirtualizerSetStrength() (0-1000)   -> %d\n", strength );
+    ALOGV("\tVirtualizerSetStrength() (0- 100)   -> %d\n", ActiveParams.CS_EffectLevel );
 
     /* Activate the initial settings */
     LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
     LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VirtualizerSetStrength")
     //ALOGV("\tVirtualizerSetStrength Succesfully called LVM_SetControlParameters\n\n");
+    LvmEffect_limitLevel(pContext);
 }    /* end setStrength */
 
 //----------------------------------------------------------------------------
@@ -1236,10 +1357,12 @@
     bool useVirtualizer = false;
 
     if (VirtualizerIsDeviceSupported(forcedDevice) != 0) {
-        // forced device is not supported, make it behave as a reset of forced mode
-        forcedDevice = AUDIO_DEVICE_NONE;
-        // but return an error
-        status = -EINVAL;
+        if (forcedDevice != AUDIO_DEVICE_NONE) {
+            //forced device is not supported, make it behave as a reset of forced mode
+            forcedDevice = AUDIO_DEVICE_NONE;
+            // but return an error
+            status = -EINVAL;
+        }
     }
 
     if (forcedDevice == AUDIO_DEVICE_NONE) {
@@ -1341,104 +1464,6 @@
 }
 
 //----------------------------------------------------------------------------
-// EqualizerLimitBandLevels()
-//----------------------------------------------------------------------------
-// Purpose: limit all EQ band gains to a value less than 0 dB while
-//          preserving the relative band levels.
-//
-// Inputs:
-//  pContext:   effect engine context
-//
-// Outputs:
-//
-//----------------------------------------------------------------------------
-void EqualizerLimitBandLevels(EffectContext *pContext) {
-    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
-    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
-
-    /* Get the current settings */
-    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
-    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerLimitBandLevels")
-    //ALOGV("\tEqualizerLimitBandLevels Succesfully returned from LVM_GetControlParameters\n");
-    //ALOGV("\tEqualizerLimitBandLevels just Got -> %d\n",
-    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
-
-    // Apply a volume correction to avoid clipping in the EQ based on 2 factors:
-    // - the maximum EQ band gain: the volume correction is such that the total of volume + max
-    // band gain is <= 0 dB
-    // - the average gain in all bands weighted by their proximity to max gain band.
-    int maxGain = 0;
-    int avgGain = 0;
-    int avgCount = 0;
-    for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
-        if (pContext->pBundledContext->bandGaindB[i] >= maxGain) {
-            int tmpMaxGain = pContext->pBundledContext->bandGaindB[i];
-            int tmpAvgGain = 0;
-            int tmpAvgCount = 0;
-            for (int j = 0; j < FIVEBAND_NUMBANDS; j++) {
-                int gain = pContext->pBundledContext->bandGaindB[j];
-                // skip current band and gains < 0 dB
-                if (j == i || gain < 0)
-                    continue;
-                // no need to continue if one band not processed yet has a higher gain than current
-                // max
-                if (gain > tmpMaxGain) {
-                    // force skipping "if (tmpAvgGain >= avgGain)" below as tmpAvgGain is not
-                    // meaningful in this case
-                    tmpAvgGain = -1;
-                    break;
-                }
-
-                int weight = 1;
-                if (j < (i + 2) && j > (i - 2))
-                    weight = 4;
-                tmpAvgGain += weight * gain;
-                tmpAvgCount += weight;
-            }
-            if (tmpAvgGain >= avgGain) {
-                maxGain = tmpMaxGain;
-                avgGain = tmpAvgGain;
-                avgCount = tmpAvgCount;
-            }
-        }
-        ActiveParams.pEQNB_BandDefinition[i].Frequency = EQNB_5BandPresetsFrequencies[i];
-        ActiveParams.pEQNB_BandDefinition[i].QFactor   = EQNB_5BandPresetsQFactors[i];
-        ActiveParams.pEQNB_BandDefinition[i].Gain = pContext->pBundledContext->bandGaindB[i];
-    }
-
-    int gainCorrection = 0;
-    if (maxGain + pContext->pBundledContext->volume > 0) {
-        gainCorrection = maxGain + pContext->pBundledContext->volume;
-    }
-    if (avgCount) {
-        gainCorrection += avgGain/avgCount;
-    }
-
-    ALOGV("EqualizerLimitBandLevels() gainCorrection %d maxGain %d avgGain %d avgCount %d",
-            gainCorrection, maxGain, avgGain, avgCount);
-
-    ActiveParams.VC_EffectLevel  = pContext->pBundledContext->volume - gainCorrection;
-    if (ActiveParams.VC_EffectLevel < -96) {
-        ActiveParams.VC_EffectLevel = -96;
-    }
-
-    /* Activate the initial settings */
-    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
-    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "EqualizerLimitBandLevels")
-    //ALOGV("\tEqualizerLimitBandLevels just Set -> %d\n",
-    //          ActiveParams.pEQNB_BandDefinition[band].Gain);
-
-    //ALOGV("\tEqualizerLimitBandLevels just set (-96dB -> 0dB)   -> %d\n",ActiveParams.VC_EffectLevel );
-    if(pContext->pBundledContext->firstVolume == LVM_TRUE){
-        LvmStatus = LVM_SetVolumeNoSmoothing(pContext->pBundledContext->hInstance, &ActiveParams);
-        LVM_ERROR_CHECK(LvmStatus, "LVM_SetVolumeNoSmoothing", "LvmBundle_process")
-        ALOGV("\tLVM_VOLUME: Disabling Smoothing for first volume change to remove spikes/clicks");
-        pContext->pBundledContext->firstVolume = LVM_FALSE;
-    }
-}
-
-
-//----------------------------------------------------------------------------
 // EqualizerGetBandLevel()
 //----------------------------------------------------------------------------
 // Purpose: Retrieve the gain currently being used for the band passed in
@@ -1480,7 +1505,8 @@
     pContext->pBundledContext->bandGaindB[band] = gainRounded;
     pContext->pBundledContext->CurPreset = PRESET_CUSTOM;
 
-    EqualizerLimitBandLevels(pContext);
+    EqualizerUpdateActiveParams(pContext);
+    LvmEffect_limitLevel(pContext);
 }
 
 //----------------------------------------------------------------------------
@@ -1615,7 +1641,8 @@
                 EQNB_5BandSoftPresets[i + preset * FIVEBAND_NUMBANDS];
     }
 
-    EqualizerLimitBandLevels(pContext);
+    EqualizerUpdateActiveParams(pContext);
+    LvmEffect_limitLevel(pContext);
 
     //ALOGV("\tEqualizerSetPreset Succesfully called LVM_SetControlParameters\n");
     return;
@@ -1670,7 +1697,7 @@
         pContext->pBundledContext->volume = level / 100;
     }
 
-    EqualizerLimitBandLevels(pContext);
+    LvmEffect_limitLevel(pContext);
 
     return 0;
 }    /* end VolumeSetVolumeLevel */
@@ -1719,7 +1746,7 @@
         pContext->pBundledContext->volume = pContext->pBundledContext->levelSaved;
     }
 
-    EqualizerLimitBandLevels(pContext);
+    LvmEffect_limitLevel(pContext);
 
     return 0;
 }    /* end setMute */
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index 420f973..b3071f4 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -142,6 +142,7 @@
                                        {1800001, 7000000},
                                        {7000001, 1}};
 
+//Note: If these frequencies change, please update LimitLevel values accordingly.
 static const LVM_UINT16  EQNB_5BandPresetsFrequencies[] = {
                                        60,           /* Frequencies in Hz */
                                        230,
@@ -192,6 +193,20 @@
                                         {"Pop"},
                                         {"Rock"}};
 
+/* The following tables have been computed using the actual levels measured by the output of
+ * white noise or pink noise (IEC268-1) for the EQ and BassBoost Effects. These are estimates of
+ * the actual energy that 'could' be present in the given band.
+ * If the frequency values in EQNB_5BandPresetsFrequencies change, these values might need to be
+ * updated.
+ */
+
+static const float LimitLevel_bandEnergyContribution[FIVEBAND_NUMBANDS] = {
+        5.0, 6.5, 6.45, 4.8, 1.7 };
+
+static const float LimitLevel_bassBoostEnergyContribution = 6.7;
+
+static const float LimitLevel_virtualizerContribution = 1.9;
+
 #if __cplusplus
 }  // extern "C"
 #endif
diff --git a/media/libeffects/testlibs/Android.mk_ b/media/libeffects/testlibs/Android.mk_
index 672ebba..14c373f 100644
--- a/media/libeffects/testlibs/Android.mk_
+++ b/media/libeffects/testlibs/Android.mk_
@@ -3,24 +3,18 @@
 # Test Reverb library
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= \
+LOCAL_SRC_FILES := \
 	EffectReverb.c.arm \
 	EffectsMath.c.arm
-LOCAL_CFLAGS+= -O2
+
+LOCAL_CFLAGS := -O2
 
 LOCAL_SHARED_LIBRARIES := \
-	libcutils
+	libcutils \
+	libdl
 
 LOCAL_MODULE_RELATIVE_PATH := soundfx
-LOCAL_MODULE:= libreverbtest
-
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-LOCAL_LDLIBS += -ldl
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
+LOCAL_MODULE := libreverbtest
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, audio-effects) \
@@ -33,7 +27,7 @@
 # Test Equalizer library
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= \
+LOCAL_SRC_FILES := \
 	EffectsMath.c.arm \
 	EffectEqualizer.cpp \
 	AudioBiquadFilter.cpp.arm \
@@ -42,21 +36,14 @@
 	AudioShelvingFilter.cpp.arm \
 	AudioEqualizer.cpp.arm
 
-LOCAL_CFLAGS+= -O2
+LOCAL_CFLAGS := -O2
 
 LOCAL_SHARED_LIBRARIES := \
-	libcutils
+	libcutils \
+	libdl
 
 LOCAL_MODULE_RELATIVE_PATH := soundfx
-LOCAL_MODULE:= libequalizertest
-
-ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
-LOCAL_LDLIBS += -ldl
-endif
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_SHARED_LIBRARIES += libdl
-endif
+LOCAL_MODULE := libequalizertest
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, graphics corecg) \
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index e012116..5378bf2 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -42,6 +42,7 @@
     mediarecorder.cpp \
     IMediaMetadataRetriever.cpp \
     mediametadataretriever.cpp \
+    MidiIoWrapper.cpp \
     ToneGenerator.cpp \
     JetPlayer.cpp \
     IOMX.cpp \
@@ -57,42 +58,26 @@
     AudioEffect.cpp \
     Visualizer.cpp \
     MemoryLeakTrackUtil.cpp \
-    SoundPool.cpp \
-    SoundPoolThread.cpp \
-    StringArray.cpp
-
-LOCAL_SRC_FILES += ../libnbaio/roundup.c
+    StringArray.cpp \
+    AudioPolicy.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libui liblog libcutils libutils libbinder libsonivox libicuuc libicui18n libexpat \
         libcamera_client libstagefright_foundation \
         libgui libdl libaudioutils libnbaio
 
-LOCAL_STATIC_LIBRARIES += libinstantssq
-
 LOCAL_WHOLE_STATIC_LIBRARIES := libmedia_helper
 
 LOCAL_MODULE:= libmedia
 
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
 LOCAL_C_INCLUDES := \
     $(TOP)/frameworks/native/include/media/openmax \
     $(TOP)/frameworks/av/include/media/ \
     $(TOP)/frameworks/av/media/libstagefright \
-    $(TOP)/external/icu/icu4c/source/common \
-    $(TOP)/external/icu/icu4c/source/i18n \
     $(call include-path-for, audio-effects) \
     $(call include-path-for, audio-utils)
 
 include $(BUILD_SHARED_LIBRARY)
 
-include $(CLEAR_VARS)
-
-# for <cutils/atomic-inline.h>
-LOCAL_CFLAGS += -DANDROID_SMP=$(if $(findstring true,$(TARGET_CPU_SMP)),1,0)
-LOCAL_SRC_FILES += SingleStateQueue.cpp
-LOCAL_CFLAGS += -DSINGLE_STATE_QUEUE_INSTANTIATIONS='"SingleStateQueueInstantiations.cpp"'
-
-LOCAL_MODULE := libinstantssq
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index 0d5d7e4..af103c1 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -150,7 +150,7 @@
     int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
     mCblk->buffer = (uint8_t *)mCblk + bufOffset;
 
-    iEffect->asBinder()->linkToDeath(mIEffectClient);
+    IInterface::asBinder(iEffect)->linkToDeath(mIEffectClient);
     mClientPid = IPCThreadState::self()->getCallingPid();
     ALOGV("set() %p OK effect: %s id: %d status %d enabled %d pid %d", this, mDescriptor.name, mId,
             mStatus, mEnabled, mClientPid);
@@ -173,7 +173,7 @@
         }
         if (mIEffect != NULL) {
             mIEffect->disconnect();
-            mIEffect->asBinder()->unlinkToDeath(mIEffectClient);
+            IInterface::asBinder(mIEffect)->unlinkToDeath(mIEffectClient);
         }
         IPCThreadState::self()->flushCommands();
     }
diff --git a/media/libmedia/AudioPolicy.cpp b/media/libmedia/AudioPolicy.cpp
new file mode 100644
index 0000000..d2d0971
--- /dev/null
+++ b/media/libmedia/AudioPolicy.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2014 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 "AudioPolicy"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include <media/AudioPolicy.h>
+
+namespace android {
+
+//
+//  AttributeMatchCriterion implementation
+//
+AttributeMatchCriterion::AttributeMatchCriterion(audio_usage_t usage,
+                                                 audio_source_t source,
+                                                 uint32_t rule)
+: mRule(rule)
+{
+    if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
+            mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
+        mAttr.mUsage = usage;
+    } else {
+        mAttr.mSource = source;
+    }
+}
+
+status_t AttributeMatchCriterion::readFromParcel(Parcel *parcel)
+{
+    mRule = parcel->readInt32();
+    if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
+            mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
+        mAttr.mUsage = (audio_usage_t)parcel->readInt32();
+    } else {
+        mAttr.mSource = (audio_source_t)parcel->readInt32();
+    }
+    return NO_ERROR;
+}
+
+status_t AttributeMatchCriterion::writeToParcel(Parcel *parcel) const
+{
+    parcel->writeInt32(mRule);
+    parcel->writeInt32(mAttr.mUsage);
+    return NO_ERROR;
+}
+
+//
+//  AudioMix implementation
+//
+
+status_t AudioMix::readFromParcel(Parcel *parcel)
+{
+    mMixType = parcel->readInt32();
+    mFormat.sample_rate = (uint32_t)parcel->readInt32();
+    mFormat.channel_mask = (audio_channel_mask_t)parcel->readInt32();
+    mFormat.format = (audio_format_t)parcel->readInt32();
+    mRouteFlags = parcel->readInt32();
+    mRegistrationId = parcel->readString8();
+    size_t size = (size_t)parcel->readInt32();
+    if (size > MAX_CRITERIA_PER_MIX) {
+        size = MAX_CRITERIA_PER_MIX;
+    }
+    for (size_t i = 0; i < size; i++) {
+        AttributeMatchCriterion criterion;
+        if (criterion.readFromParcel(parcel) == NO_ERROR) {
+            mCriteria.add(criterion);
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t AudioMix::writeToParcel(Parcel *parcel) const
+{
+    parcel->writeInt32(mMixType);
+    parcel->writeInt32(mFormat.sample_rate);
+    parcel->writeInt32(mFormat.channel_mask);
+    parcel->writeInt32(mFormat.format);
+    parcel->writeInt32(mRouteFlags);
+    parcel->writeString8(mRegistrationId);
+    size_t size = mCriteria.size();
+    if (size > MAX_CRITERIA_PER_MIX) {
+        size = MAX_CRITERIA_PER_MIX;
+    }
+    size_t sizePosition = parcel->dataPosition();
+    parcel->writeInt32(size);
+    size_t finalSize = size;
+    for (size_t i = 0; i < size; i++) {
+        size_t position = parcel->dataPosition();
+        if (mCriteria[i].writeToParcel(parcel) != NO_ERROR) {
+            parcel->setDataPosition(position);
+            finalSize--;
+        }
+    }
+    if (size != finalSize) {
+        size_t position = parcel->dataPosition();
+        parcel->setDataPosition(sizePosition);
+        parcel->writeInt32(finalSize);
+        parcel->setDataPosition(position);
+    }
+    return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 9e7ba88..84077ec 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -82,14 +82,16 @@
         uint32_t notificationFrames,
         int sessionId,
         transfer_type transferType,
-        audio_input_flags_t flags)
+        audio_input_flags_t flags,
+        const audio_attributes_t* pAttributes)
     : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT),
       mProxy(NULL)
 {
     mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
-            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags);
+            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
+            pAttributes);
 }
 
 AudioRecord::~AudioRecord()
@@ -105,7 +107,7 @@
             mAudioRecordThread->requestExitAndWait();
             mAudioRecordThread.clear();
         }
-        mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
+        IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
         mAudioRecord.clear();
         mCblkMemory.clear();
         mBufferMemory.clear();
@@ -126,7 +128,8 @@
         bool threadCanCallJava,
         int sessionId,
         transfer_type transferType,
-        audio_input_flags_t flags)
+        audio_input_flags_t flags,
+        const audio_attributes_t* pAttributes)
 {
     ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
           "notificationFrames %u, sessionId %d, transferType %d, flags %#x",
@@ -164,11 +167,15 @@
         return INVALID_OPERATION;
     }
 
-    // handle default values first.
-    if (inputSource == AUDIO_SOURCE_DEFAULT) {
-        inputSource = AUDIO_SOURCE_MIC;
+    if (pAttributes == NULL) {
+        memset(&mAttributes, 0, sizeof(audio_attributes_t));
+        mAttributes.source = inputSource;
+    } else {
+        // stream type shouldn't be looked at, this track has audio attributes
+        memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
+        ALOGV("Building AudioRecord with attributes: source=%d flags=0x%x tags=[%s]",
+              mAttributes.source, mAttributes.flags, mAttributes.tags);
     }
-    mInputSource = inputSource;
 
     if (sampleRate == 0) {
         ALOGE("Invalid sample rate %u", sampleRate);
@@ -345,6 +352,10 @@
     mMarkerPosition = marker;
     mMarkerReached = false;
 
+    sp<AudioRecordThread> t = mAudioRecordThread;
+    if (t != 0) {
+        t->wake();
+    }
     return NO_ERROR;
 }
 
@@ -371,6 +382,10 @@
     mNewPosition = mProxy->getPosition() + updatePeriod;
     mUpdatePeriod = updatePeriod;
 
+    sp<AudioRecordThread> t = mAudioRecordThread;
+    if (t != 0) {
+        t->wake();
+    }
     return NO_ERROR;
 }
 
@@ -444,12 +459,14 @@
         }
     }
 
-    audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat,
-            mChannelMask, mSessionId, mFlags);
-    if (input == AUDIO_IO_HANDLE_NONE) {
+    audio_io_handle_t input;
+    status = AudioSystem::getInputForAttr(&mAttributes, &input, (audio_session_t)mSessionId,
+                                        mSampleRate, mFormat, mChannelMask, mFlags);
+
+    if (status != NO_ERROR) {
         ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, "
               "channel mask %#x, session %d, flags %#x",
-              mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId, mFlags);
+              mAttributes.source, mSampleRate, mFormat, mChannelMask, mSessionId, mFlags);
         return BAD_VALUE;
     }
     {
@@ -516,7 +533,7 @@
 
     // invariant that mAudioRecord != 0 is true only after set() returns successfully
     if (mAudioRecord != 0) {
-        mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
+        IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
         mDeathNotifier.clear();
     }
     mAudioRecord = record;
@@ -566,7 +583,7 @@
     mProxy->setMinimum(mNotificationFramesAct);
 
     mDeathNotifier = new DeathNotifier(this);
-    mAudioRecord->asBinder()->linkToDeath(mDeathNotifier, this);
+    IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);
 
     return NO_ERROR;
     }
@@ -854,8 +871,11 @@
     if (!markerReached && position < markerPosition) {
         minFrames = markerPosition - position;
     }
-    if (updatePeriod > 0 && updatePeriod < minFrames) {
-        minFrames = updatePeriod;
+    if (updatePeriod > 0) {
+        uint32_t remaining = newPosition - position;
+        if (remaining < minFrames) {
+            minFrames = remaining;
+        }
     }
 
     // If > 0, poll periodically to recover from a stuck server.  A good value is 2.
@@ -1060,8 +1080,8 @@
     case NS_NEVER:
         return false;
     case NS_WHENEVER:
-        // FIXME increase poll interval, or make event-driven
-        ns = 1000000000LL;
+        // Event driven: call wake() when callback notifications conditions change.
+        ns = INT64_MAX;
         // fall through
     default:
         LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns);
@@ -1094,6 +1114,17 @@
     }
 }
 
+void AudioRecord::AudioRecordThread::wake()
+{
+    AutoMutex _l(mMyLock);
+    if (!mPaused && mPausedInt && mPausedNs > 0) {
+        // audio record is active and internally paused with timeout.
+        mIgnoreNextPausedInt = true;
+        mPausedInt = false;
+        mMyCond.signal();
+    }
+}
+
 void AudioRecord::AudioRecordThread::pauseInternal(nsecs_t ns)
 {
     AutoMutex _l(mMyLock);
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index dda3657..f5a5712 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -32,6 +32,9 @@
 
 // client singleton for AudioFlinger binder interface
 Mutex AudioSystem::gLock;
+Mutex AudioSystem::gLockCache;
+Mutex AudioSystem::gLockAPS;
+Mutex AudioSystem::gLockAPC;
 sp<IAudioFlinger> AudioSystem::gAudioFlinger;
 sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
 audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
@@ -48,33 +51,40 @@
 sp<AudioSystem::AudioPortCallback> AudioSystem::gAudioPortCallback;
 
 // establish binder interface to AudioFlinger service
-const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
+const sp<IAudioFlinger> AudioSystem::get_audio_flinger()
 {
-    Mutex::Autolock _l(gLock);
-    if (gAudioFlinger == 0) {
-        sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder;
-        do {
-            binder = sm->getService(String16("media.audio_flinger"));
-            if (binder != 0)
-                break;
-            ALOGW("AudioFlinger not published, waiting...");
-            usleep(500000); // 0.5 s
-        } while (true);
-        if (gAudioFlingerClient == NULL) {
-            gAudioFlingerClient = new AudioFlingerClient();
-        } else {
-            if (gAudioErrorCallback) {
-                gAudioErrorCallback(NO_ERROR);
+    sp<IAudioFlinger> af;
+    sp<AudioFlingerClient> afc;
+    {
+        Mutex::Autolock _l(gLock);
+        if (gAudioFlinger == 0) {
+            sp<IServiceManager> sm = defaultServiceManager();
+            sp<IBinder> binder;
+            do {
+                binder = sm->getService(String16("media.audio_flinger"));
+                if (binder != 0)
+                    break;
+                ALOGW("AudioFlinger not published, waiting...");
+                usleep(500000); // 0.5 s
+            } while (true);
+            if (gAudioFlingerClient == NULL) {
+                gAudioFlingerClient = new AudioFlingerClient();
+            } else {
+                if (gAudioErrorCallback) {
+                    gAudioErrorCallback(NO_ERROR);
+                }
             }
+            binder->linkToDeath(gAudioFlingerClient);
+            gAudioFlinger = interface_cast<IAudioFlinger>(binder);
+            LOG_ALWAYS_FATAL_IF(gAudioFlinger == 0);
+            afc = gAudioFlingerClient;
         }
-        binder->linkToDeath(gAudioFlingerClient);
-        gAudioFlinger = interface_cast<IAudioFlinger>(binder);
-        gAudioFlinger->registerClient(gAudioFlingerClient);
+        af = gAudioFlinger;
     }
-    ALOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
-
-    return gAudioFlinger;
+    if (afc != 0) {
+        af->registerClient(afc);
+    }
+    return af;
 }
 
 /* static */ status_t AudioSystem::checkAudioFlinger()
@@ -245,36 +255,23 @@
     return getSamplingRate(output, samplingRate);
 }
 
-status_t AudioSystem::getOutputSamplingRateForAttr(uint32_t* samplingRate,
-        const audio_attributes_t *attr)
-{
-    if (attr == NULL) {
-        return BAD_VALUE;
-    }
-    audio_io_handle_t output = getOutputForAttr(attr);
-    if (output == 0) {
-        return PERMISSION_DENIED;
-    }
-    return getSamplingRate(output, samplingRate);
-}
-
 status_t AudioSystem::getSamplingRate(audio_io_handle_t output,
                                       uint32_t* samplingRate)
 {
-    OutputDescriptor *outputDesc;
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
 
-    gLock.lock();
-    outputDesc = AudioSystem::gOutputs.valueFor(output);
+    Mutex::Autolock _l(gLockCache);
+
+    OutputDescriptor *outputDesc = AudioSystem::gOutputs.valueFor(output);
     if (outputDesc == NULL) {
         ALOGV("getOutputSamplingRate() no output descriptor for output %d in gOutputs", output);
-        gLock.unlock();
-        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-        if (af == 0) return PERMISSION_DENIED;
+        gLockCache.unlock();
         *samplingRate = af->sampleRate(output);
+        gLockCache.lock();
     } else {
         ALOGV("getOutputSamplingRate() reading from output desc");
         *samplingRate = outputDesc->samplingRate;
-        gLock.unlock();
     }
     if (*samplingRate == 0) {
         ALOGE("AudioSystem::getSamplingRate failed for output %d", output);
@@ -305,18 +302,18 @@
 status_t AudioSystem::getFrameCount(audio_io_handle_t output,
                                     size_t* frameCount)
 {
-    OutputDescriptor *outputDesc;
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
 
-    gLock.lock();
-    outputDesc = AudioSystem::gOutputs.valueFor(output);
+    Mutex::Autolock _l(gLockCache);
+
+    OutputDescriptor *outputDesc = AudioSystem::gOutputs.valueFor(output);
     if (outputDesc == NULL) {
-        gLock.unlock();
-        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-        if (af == 0) return PERMISSION_DENIED;
+        gLockCache.unlock();
         *frameCount = af->frameCount(output);
+        gLockCache.lock();
     } else {
         *frameCount = outputDesc->frameCount;
-        gLock.unlock();
     }
     if (*frameCount == 0) {
         ALOGE("AudioSystem::getFrameCount failed for output %d", output);
@@ -347,18 +344,18 @@
 status_t AudioSystem::getLatency(audio_io_handle_t output,
                                  uint32_t* latency)
 {
-    OutputDescriptor *outputDesc;
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
 
-    gLock.lock();
-    outputDesc = AudioSystem::gOutputs.valueFor(output);
+    Mutex::Autolock _l(gLockCache);
+
+    OutputDescriptor *outputDesc = AudioSystem::gOutputs.valueFor(output);
     if (outputDesc == NULL) {
-        gLock.unlock();
-        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-        if (af == 0) return PERMISSION_DENIED;
+        gLockCache.unlock();
         *latency = af->latency(output);
+        gLockCache.lock();
     } else {
         *latency = outputDesc->latency;
-        gLock.unlock();
     }
 
     ALOGV("getLatency() output %d, latency %d", output, *latency);
@@ -369,24 +366,24 @@
 status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, audio_format_t format,
         audio_channel_mask_t channelMask, size_t* buffSize)
 {
-    gLock.lock();
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        return PERMISSION_DENIED;
+    }
+    Mutex::Autolock _l(gLockCache);
     // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values
     size_t inBuffSize = gInBuffSize;
     if ((inBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat)
         || (channelMask != gPrevInChannelMask)) {
-        gLock.unlock();
-        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
-        if (af == 0) {
-            return PERMISSION_DENIED;
-        }
+        gLockCache.unlock();
         inBuffSize = af->getInputBufferSize(sampleRate, format, channelMask);
+        gLockCache.lock();
         if (inBuffSize == 0) {
             ALOGE("AudioSystem::getInputBufferSize failed sampleRate %d format %#x channelMask %x",
                     sampleRate, format, channelMask);
             return BAD_VALUE;
         }
         // A benign race is possible here: we could overwrite a fresher cache entry
-        gLock.lock();
         // save the request params
         gPrevInSamplingRate = sampleRate;
         gPrevInFormat = format;
@@ -394,7 +391,6 @@
 
         gInBuffSize = inBuffSize;
     }
-    gLock.unlock();
     *buffSize = inBuffSize;
 
     return NO_ERROR;
@@ -461,14 +457,21 @@
 
 void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who __unused)
 {
-    Mutex::Autolock _l(AudioSystem::gLock);
+    audio_error_callback cb = NULL;
+    {
+        Mutex::Autolock _l(AudioSystem::gLock);
+        AudioSystem::gAudioFlinger.clear();
+        cb = gAudioErrorCallback;
+    }
 
-    AudioSystem::gAudioFlinger.clear();
-    // clear output handles and stream to output map caches
-    AudioSystem::gOutputs.clear();
+    {
+        // clear output handles and stream to output map caches
+        Mutex::Autolock _l(gLockCache);
+        AudioSystem::gOutputs.clear();
+    }
 
-    if (gAudioErrorCallback) {
-        gAudioErrorCallback(DEAD_OBJECT);
+    if (cb) {
+        cb(DEAD_OBJECT);
     }
     ALOGW("AudioFlinger server died!");
 }
@@ -481,7 +484,7 @@
 
     if (ioHandle == AUDIO_IO_HANDLE_NONE) return;
 
-    Mutex::Autolock _l(AudioSystem::gLock);
+    Mutex::Autolock _l(AudioSystem::gLockCache);
 
     switch (event) {
     case STREAM_CONFIG_CHANGED:
@@ -496,8 +499,8 @@
 
         OutputDescriptor *outputDesc =  new OutputDescriptor(*desc);
         gOutputs.add(ioHandle, outputDesc);
-        ALOGV("ioConfigChanged() new output samplingRate %u, format %#x channel mask %#x frameCount %zu "
-                "latency %d",
+        ALOGV("ioConfigChanged() new output samplingRate %u, format %#x channel mask %#x "
+                "frameCount %zu latency %d",
                 outputDesc->samplingRate, outputDesc->format, outputDesc->channelMask,
                 outputDesc->frameCount, outputDesc->latency);
         } break;
@@ -520,8 +523,8 @@
         if (param2 == NULL) break;
         desc = (const OutputDescriptor *)param2;
 
-        ALOGV("ioConfigChanged() new config for output %d samplingRate %u, format %#x channel mask %#x "
-                "frameCount %zu latency %d",
+        ALOGV("ioConfigChanged() new config for output %d samplingRate %u, format %#x "
+                "channel mask %#x frameCount %zu latency %d",
                 ioHandle, desc->samplingRate, desc->format,
                 desc->channelMask, desc->frameCount, desc->latency);
         OutputDescriptor *outputDesc = gOutputs.valueAt(index);
@@ -543,73 +546,66 @@
     gAudioErrorCallback = cb;
 }
 
-
-bool AudioSystem::routedToA2dpOutput(audio_stream_type_t streamType)
-{
-    switch (streamType) {
-    case AUDIO_STREAM_MUSIC:
-    case AUDIO_STREAM_VOICE_CALL:
-    case AUDIO_STREAM_BLUETOOTH_SCO:
-    case AUDIO_STREAM_SYSTEM:
-        return true;
-    default:
-        return false;
-    }
-}
-
-
 // client singleton for AudioPolicyService binder interface
+// protected by gLockAPS
 sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
 sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient;
 
 
 // establish binder interface to AudioPolicy service
-const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service()
+const sp<IAudioPolicyService> AudioSystem::get_audio_policy_service()
 {
-    gLock.lock();
-    if (gAudioPolicyService == 0) {
-        sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder;
-        do {
-            binder = sm->getService(String16("media.audio_policy"));
-            if (binder != 0)
-                break;
-            ALOGW("AudioPolicyService not published, waiting...");
-            usleep(500000); // 0.5 s
-        } while (true);
-        if (gAudioPolicyServiceClient == NULL) {
-            gAudioPolicyServiceClient = new AudioPolicyServiceClient();
+    sp<IAudioPolicyService> ap;
+    sp<AudioPolicyServiceClient> apc;
+    {
+        Mutex::Autolock _l(gLockAPS);
+        if (gAudioPolicyService == 0) {
+            sp<IServiceManager> sm = defaultServiceManager();
+            sp<IBinder> binder;
+            do {
+                binder = sm->getService(String16("media.audio_policy"));
+                if (binder != 0)
+                    break;
+                ALOGW("AudioPolicyService not published, waiting...");
+                usleep(500000); // 0.5 s
+            } while (true);
+            if (gAudioPolicyServiceClient == NULL) {
+                gAudioPolicyServiceClient = new AudioPolicyServiceClient();
+            }
+            binder->linkToDeath(gAudioPolicyServiceClient);
+            gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
+            LOG_ALWAYS_FATAL_IF(gAudioPolicyService == 0);
+            apc = gAudioPolicyServiceClient;
         }
-        binder->linkToDeath(gAudioPolicyServiceClient);
-        gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
-        gLock.unlock();
-        // Registering the client takes the AudioPolicyService lock.
-        // Don't hold the AudioSystem lock at the same time.
-        gAudioPolicyService->registerClient(gAudioPolicyServiceClient);
-    } else {
-        // There exists a benign race condition where gAudioPolicyService
-        // is set, but gAudioPolicyServiceClient is not yet registered.
-        gLock.unlock();
+        ap = gAudioPolicyService;
     }
-    return gAudioPolicyService;
+    if (apc != 0) {
+        ap->registerClient(apc);
+    }
+
+    return ap;
 }
 
 // ---------------------------------------------------------------------------
 
 status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
                                                audio_policy_dev_state_t state,
-                                               const char *device_address)
+                                               const char *device_address,
+                                               const char *device_name)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     const char *address = "";
+    const char *name = "";
 
     if (aps == 0) return PERMISSION_DENIED;
 
     if (device_address != NULL) {
         address = device_address;
     }
-
-    return aps->setDeviceConnectionState(device, state, address);
+    if (device_name != NULL) {
+        name = device_name;
+    }
+    return aps->setDeviceConnectionState(device, state, address, name);
 }
 
 audio_policy_dev_state_t AudioSystem::getDeviceConnectionState(audio_devices_t device,
@@ -657,22 +653,26 @@
     return aps->getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo);
 }
 
-audio_io_handle_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags,
-                                    const audio_offload_info_t *offloadInfo)
+status_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
+                                        audio_io_handle_t *output,
+                                        audio_session_t session,
+                                        audio_stream_type_t *stream,
+                                        uint32_t samplingRate,
+                                        audio_format_t format,
+                                        audio_channel_mask_t channelMask,
+                                        audio_output_flags_t flags,
+                                        const audio_offload_info_t *offloadInfo)
 {
-    if (attr == NULL) return 0;
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
-    if (aps == 0) return 0;
-    return aps->getOutputForAttr(attr, samplingRate, format, channelMask, flags, offloadInfo);
+    if (aps == 0) return NO_INIT;
+    return aps->getOutputForAttr(attr, output, session, stream,
+                                 samplingRate, format, channelMask,
+                                 flags, offloadInfo);
 }
 
 status_t AudioSystem::startOutput(audio_io_handle_t output,
                                   audio_stream_type_t stream,
-                                  int session)
+                                  audio_session_t session)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
@@ -681,30 +681,33 @@
 
 status_t AudioSystem::stopOutput(audio_io_handle_t output,
                                  audio_stream_type_t stream,
-                                 int session)
+                                 audio_session_t session)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
     return aps->stopOutput(output, stream, session);
 }
 
-void AudioSystem::releaseOutput(audio_io_handle_t output)
+void AudioSystem::releaseOutput(audio_io_handle_t output,
+                                audio_stream_type_t stream,
+                                audio_session_t session)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return;
-    aps->releaseOutput(output);
+    aps->releaseOutput(output, stream, session);
 }
 
-audio_io_handle_t AudioSystem::getInput(audio_source_t inputSource,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    int sessionId,
-                                    audio_input_flags_t flags)
+status_t AudioSystem::getInputForAttr(const audio_attributes_t *attr,
+                                audio_io_handle_t *input,
+                                audio_session_t session,
+                                uint32_t samplingRate,
+                                audio_format_t format,
+                                audio_channel_mask_t channelMask,
+                                audio_input_flags_t flags)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
-    if (aps == 0) return 0;
-    return aps->getInput(inputSource, samplingRate, format, channelMask, sessionId, flags);
+    if (aps == 0) return NO_INIT;
+    return aps->getInputForAttr(attr, input, session, samplingRate, format, channelMask, flags);
 }
 
 status_t AudioSystem::startInput(audio_io_handle_t input,
@@ -856,9 +859,21 @@
 
 void AudioSystem::clearAudioConfigCache()
 {
-    Mutex::Autolock _l(gLock);
+    // called by restoreTrack_l(), which needs new IAudioFlinger and IAudioPolicyService instances
     ALOGV("clearAudioConfigCache()");
-    gOutputs.clear();
+    {
+        Mutex::Autolock _l(gLockCache);
+        gOutputs.clear();
+    }
+    {
+        Mutex::Autolock _l(gLock);
+        gAudioFlinger.clear();
+    }
+    {
+        Mutex::Autolock _l(gLockAPS);
+        gAudioPolicyService.clear();
+    }
+    // Do not clear gAudioPortCallback
 }
 
 bool AudioSystem::isOffloadSupported(const audio_offload_info_t& info)
@@ -920,7 +935,7 @@
 
 void AudioSystem::setAudioPortCallback(sp<AudioPortCallback> callBack)
 {
-    Mutex::Autolock _l(gLock);
+    Mutex::Autolock _l(gLockAPC);
     gAudioPortCallback = callBack;
 }
 
@@ -947,23 +962,34 @@
     return aps->getPhoneState();
 }
 
+status_t AudioSystem::registerPolicyMixes(Vector<AudioMix> mixes, bool registration)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->registerPolicyMixes(mixes, registration);
+}
 
 // ---------------------------------------------------------------------------
 
 void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused)
 {
-    Mutex::Autolock _l(gLock);
-    if (gAudioPortCallback != 0) {
-        gAudioPortCallback->onServiceDied();
+    {
+        Mutex::Autolock _l(gLockAPC);
+        if (gAudioPortCallback != 0) {
+            gAudioPortCallback->onServiceDied();
+        }
     }
-    AudioSystem::gAudioPolicyService.clear();
+    {
+        Mutex::Autolock _l(gLockAPS);
+        AudioSystem::gAudioPolicyService.clear();
+    }
 
     ALOGW("AudioPolicyService server died!");
 }
 
 void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
 {
-    Mutex::Autolock _l(gLock);
+    Mutex::Autolock _l(gLockAPC);
     if (gAudioPortCallback != 0) {
         gAudioPortCallback->onAudioPortListUpdate();
     }
@@ -971,7 +997,7 @@
 
 void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate()
 {
-    Mutex::Autolock _l(gLock);
+    Mutex::Autolock _l(gLockAPC);
     if (gAudioPortCallback != 0) {
         gAudioPortCallback->onAudioPatchListUpdate();
     }
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 082a5e1..c775e7b 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -28,15 +28,21 @@
 #include <utils/Log.h>
 #include <private/media/AudioTrackShared.h>
 #include <media/IAudioFlinger.h>
+#include <media/AudioPolicyHelper.h>
 #include <media/AudioResamplerPublic.h>
 
 #define WAIT_PERIOD_MS                  10
 #define WAIT_STREAM_END_TIMEOUT_SEC     120
-
+static const int kMaxLoopCountNotifications = 32;
 
 namespace android {
 // ---------------------------------------------------------------------------
 
+template <typename T>
+const T &min(const T &x, const T &y) {
+    return x < y ? x : y;
+}
+
 static int64_t convertTimespecToUs(const struct timespec &tv)
 {
     return tv.tv_sec * 1000000ll + tv.tv_nsec / 1000;
@@ -60,12 +66,11 @@
         return BAD_VALUE;
     }
 
-    // FIXME merge with similar code in createTrack_l(), except we're missing
-    //       some information here that is available in createTrack_l():
+    // FIXME handle in server, like createTrack_l(), possible missing info:
     //          audio_io_handle_t output
     //          audio_format_t format
     //          audio_channel_mask_t channelMask
-    //          audio_output_flags_t flags
+    //          audio_output_flags_t flags (FAST)
     uint32_t afSampleRate;
     status_t status;
     status = AudioSystem::getOutputSamplingRate(&afSampleRate, streamType);
@@ -95,16 +100,16 @@
         minBufCount = 2;
     }
 
-    *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount :
-            afFrameCount * minBufCount * uint64_t(sampleRate) / afSampleRate;
-    // The formula above should always produce a non-zero value, but return an error
-    // in the unlikely event that it does not, as that's part of the API contract.
+    *frameCount = minBufCount * sourceFramesNeeded(sampleRate, afFrameCount, afSampleRate);
+    // The formula above should always produce a non-zero value under normal circumstances:
+    // AudioTrack.SAMPLE_RATE_HZ_MIN <= sampleRate <= AudioTrack.SAMPLE_RATE_HZ_MAX.
+    // Return error in the unlikely event that it does not, as that's part of the API contract.
     if (*frameCount == 0) {
-        ALOGE("AudioTrack::getMinFrameCount failed for streamType %d, sampleRate %d",
+        ALOGE("AudioTrack::getMinFrameCount failed for streamType %d, sampleRate %u",
                 streamType, sampleRate);
         return BAD_VALUE;
     }
-    ALOGV("getMinFrameCount=%zu: afFrameCount=%zu, minBufCount=%d, afSampleRate=%d, afLatency=%d",
+    ALOGV("getMinFrameCount=%zu: afFrameCount=%zu, minBufCount=%u, afSampleRate=%u, afLatency=%u",
             *frameCount, afFrameCount, minBufCount, afSampleRate, afLatency);
     return NO_ERROR;
 }
@@ -193,7 +198,7 @@
             mAudioTrackThread->requestExitAndWait();
             mAudioTrackThread.clear();
         }
-        mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this);
+        IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
         mAudioTrack.clear();
         mCblkMemory.clear();
         mSharedBuffer.clear();
@@ -278,42 +283,26 @@
     }
 
     // handle default values first.
-    // TODO once AudioPolicyManager fully supports audio_attributes_t,
-    //   remove stream "text-to-speech" redirect
-    if ((streamType == AUDIO_STREAM_DEFAULT) || (streamType == AUDIO_STREAM_TTS)) {
+    if (streamType == AUDIO_STREAM_DEFAULT) {
         streamType = AUDIO_STREAM_MUSIC;
     }
-
     if (pAttributes == NULL) {
-        if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
+        if (uint32_t(streamType) >= AUDIO_STREAM_PUBLIC_CNT) {
             ALOGE("Invalid stream type %d", streamType);
             return BAD_VALUE;
         }
-        setAttributesFromStreamType(streamType);
         mStreamType = streamType;
+
     } else {
-        if (!isValidAttributes(pAttributes)) {
-            ALOGE("Invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
-                pAttributes->usage, pAttributes->content_type, pAttributes->flags,
-                pAttributes->tags);
-        }
         // stream type shouldn't be looked at, this track has audio attributes
         memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
-        setStreamTypeFromAttributes(mAttributes);
         ALOGV("Building AudioTrack with attributes: usage=%d content=%d flags=0x%x tags=[%s]",
                 mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags);
-    }
-
-    status_t status;
-    if (sampleRate == 0) {
-        status = AudioSystem::getOutputSamplingRateForAttr(&sampleRate, &mAttributes);
-        if (status != NO_ERROR) {
-            ALOGE("Could not get output sample rate for stream type %d; status %d",
-                    mStreamType, status);
-            return status;
+        mStreamType = AUDIO_STREAM_DEFAULT;
+        if ((mAttributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
+            flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
         }
     }
-    mSampleRate = sampleRate;
 
     // these below should probably come from the audioFlinger too...
     if (format == AUDIO_FORMAT_DEFAULT) {
@@ -335,12 +324,6 @@
     uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
     mChannelCount = channelCount;
 
-    // AudioFlinger does not currently support 8-bit data in shared memory
-    if (format == AUDIO_FORMAT_PCM_8_BIT && sharedBuffer != 0) {
-        ALOGE("8-bit data in shared memory is not supported");
-        return BAD_VALUE;
-    }
-
     // force direct flag if format is not linear PCM
     // or offload was requested
     if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
@@ -352,9 +335,10 @@
                 // FIXME why can't we allow direct AND fast?
                 ((flags | AUDIO_OUTPUT_FLAG_DIRECT) & ~AUDIO_OUTPUT_FLAG_FAST);
     }
-    // only allow deep buffering for music stream type
-    if (mStreamType != AUDIO_STREAM_MUSIC) {
-        flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
+
+    // force direct flag if HW A/V sync requested
+    if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
+        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
     }
 
     if (flags & AUDIO_OUTPUT_FLAG_DIRECT) {
@@ -363,16 +347,19 @@
         } else {
             mFrameSize = sizeof(uint8_t);
         }
-        mFrameSizeAF = mFrameSize;
     } else {
         ALOG_ASSERT(audio_is_linear_pcm(format));
         mFrameSize = channelCount * audio_bytes_per_sample(format);
-        mFrameSizeAF = channelCount * audio_bytes_per_sample(
-                format == AUDIO_FORMAT_PCM_8_BIT ? AUDIO_FORMAT_PCM_16_BIT : format);
         // createTrack will return an error if PCM format is not supported by server,
         // so no need to check for specific PCM formats here
     }
 
+    // sampling rate must be specified for direct outputs
+    if (sampleRate == 0 && (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
+        return BAD_VALUE;
+    }
+    mSampleRate = sampleRate;
+
     // Make copy of input parameter offloadInfo so that in the future:
     //  (a) createTrack_l doesn't need it as an input parameter
     //  (b) we can support re-creation of offloaded tracks
@@ -390,7 +377,11 @@
     mReqFrameCount = frameCount;
     mNotificationFramesReq = notificationFrames;
     mNotificationFramesAct = 0;
-    mSessionId = sessionId;
+    if (sessionId == AUDIO_SESSION_ALLOCATE) {
+        mSessionId = AudioSystem::newAudioUniqueId();
+    } else {
+        mSessionId = sessionId;
+    }
     int callingpid = IPCThreadState::self()->getCallingPid();
     int mypid = getpid();
     if (uid == -1 || (callingpid != mypid)) {
@@ -413,7 +404,7 @@
     }
 
     // create the IAudioTrack
-    status = createTrack_l();
+    status_t status = createTrack_l();
 
     if (status != NO_ERROR) {
         if (mAudioTrackThread != 0) {
@@ -427,7 +418,10 @@
     mStatus = NO_ERROR;
     mState = STATE_STOPPED;
     mUserData = user;
-    mLoopPeriod = 0;
+    mLoopCount = 0;
+    mLoopStart = 0;
+    mLoopEnd = 0;
+    mLoopCountNotified = 0;
     mMarkerPosition = 0;
     mMarkerReached = false;
     mNewPosition = 0;
@@ -538,14 +532,12 @@
     // the playback head position will reset to 0, so if a marker is set, we need
     // to activate it again
     mMarkerReached = false;
-#if 0
-    // Force flush if a shared buffer is used otherwise audioflinger
-    // will not stop before end of buffer is reached.
-    // It may be needed to make sure that we stop playback, likely in case looping is on.
+
     if (mSharedBuffer != 0) {
-        flush_l();
+        // clear buffer position and loop count.
+        mStaticProxy->setBufferPositionAndLoop(0 /* position */,
+                0 /* loopStart */, 0 /* loopEnd */, 0 /* loopCount */);
     }
-#endif
 
     sp<AudioTrackThread> t = mAudioTrackThread;
     if (t != 0) {
@@ -680,15 +672,18 @@
         return INVALID_OPERATION;
     }
 
+    AutoMutex lock(mLock);
+    if (mOutput == AUDIO_IO_HANDLE_NONE) {
+        return NO_INIT;
+    }
     uint32_t afSamplingRate;
-    if (AudioSystem::getOutputSamplingRateForAttr(&afSamplingRate, &mAttributes) != NO_ERROR) {
+    if (AudioSystem::getSamplingRate(mOutput, &afSamplingRate) != NO_ERROR) {
         return NO_INIT;
     }
     if (rate == 0 || rate > afSamplingRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) {
         return BAD_VALUE;
     }
 
-    AutoMutex lock(mLock);
     mSampleRate = rate;
     mProxy->setSampleRate(rate);
 
@@ -744,11 +739,15 @@
 
 void AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount)
 {
-    // FIXME If setting a loop also sets position to start of loop, then
-    //       this is correct.  Otherwise it should be removed.
-    mNewPosition = updateAndGetPosition_l() + mUpdatePeriod;
-    mLoopPeriod = loopCount != 0 ? loopEnd - loopStart : 0;
+    // We do not update the periodic notification point.
+    // mNewPosition = updateAndGetPosition_l() + mUpdatePeriod;
+    mLoopCount = loopCount;
+    mLoopEnd = loopEnd;
+    mLoopStart = loopStart;
+    mLoopCountNotified = loopCount;
     mStaticProxy->setLoop(loopStart, loopEnd, loopCount);
+
+    // Waking the AudioTrackThread is not needed as this cannot be called when active.
 }
 
 status_t AudioTrack::setMarkerPosition(uint32_t marker)
@@ -762,6 +761,10 @@
     mMarkerPosition = marker;
     mMarkerReached = false;
 
+    sp<AudioTrackThread> t = mAudioTrackThread;
+    if (t != 0) {
+        t->wake();
+    }
     return NO_ERROR;
 }
 
@@ -791,6 +794,10 @@
     mNewPosition = updateAndGetPosition_l() + updatePeriod;
     mUpdatePeriod = updatePeriod;
 
+    sp<AudioTrackThread> t = mAudioTrackThread;
+    if (t != 0) {
+        t->wake();
+    }
     return NO_ERROR;
 }
 
@@ -828,12 +835,11 @@
     if (mState == STATE_ACTIVE) {
         return INVALID_OPERATION;
     }
+    // After setting the position, use full update period before notification.
     mNewPosition = updateAndGetPosition_l() + mUpdatePeriod;
-    mLoopPeriod = 0;
-    // FIXME Check whether loops and setting position are incompatible in old code.
-    // If we use setLoop for both purposes we lose the capability to set the position while looping.
-    mStaticProxy->setLoop(position, mFrameCount, 0);
+    mStaticProxy->setBufferPosition(position);
 
+    // Waking the AudioTrackThread is not needed as this cannot be called when active.
     return NO_ERROR;
 }
 
@@ -861,6 +867,10 @@
         // due to hardware latency. We leave this behavior for now.
         *position = dspFrames;
     } else {
+        if (mCblk->mFlags & CBLK_INVALID) {
+            restoreTrack_l("getPosition");
+        }
+
         // IAudioTrack::stop() isn't synchronous; we don't know when presentation completes
         *position = (mState == STATE_STOPPED || mState == STATE_FLUSHED) ?
                 0 : updateAndGetPosition_l();
@@ -894,10 +904,18 @@
         return INVALID_OPERATION;
     }
     mNewPosition = mUpdatePeriod;
-    mLoopPeriod = 0;
-    // FIXME The new code cannot reload while keeping a loop specified.
-    // Need to check how the old code handled this, and whether it's a significant change.
-    mStaticProxy->setLoop(0, mFrameCount, 0);
+    (void) updateAndGetPosition_l();
+    mPosition = 0;
+#if 0
+    // The documentation is not clear on the behavior of reload() and the restoration
+    // of loop count. Historically we have not restored loop count, start, end,
+    // but it makes sense if one desires to repeat playing a particular sound.
+    if (mLoopCount != 0) {
+        mLoopCountNotified = mLoopCount;
+        mStaticProxy->setLoop(mLoopStart, mLoopEnd, mLoopCount);
+    }
+#endif
+    mStaticProxy->setBufferPosition(0);
     return NO_ERROR;
 }
 
@@ -917,24 +935,38 @@
     return status;
 }
 
+audio_stream_type_t AudioTrack::streamType() const
+{
+    if (mStreamType == AUDIO_STREAM_DEFAULT) {
+        return audio_attributes_to_stream_type(&mAttributes);
+    }
+    return mStreamType;
+}
+
 // -------------------------------------------------------------------------
 
 // must be called with mLock held
 status_t AudioTrack::createTrack_l()
 {
-    status_t status;
     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
     if (audioFlinger == 0) {
         ALOGE("Could not get audioflinger");
         return NO_INIT;
     }
 
-    audio_io_handle_t output = AudioSystem::getOutputForAttr(&mAttributes, mSampleRate, mFormat,
-            mChannelMask, mFlags, mOffloadInfo);
-    if (output == AUDIO_IO_HANDLE_NONE) {
+    audio_io_handle_t output;
+    audio_stream_type_t streamType = mStreamType;
+    audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
+    status_t status = AudioSystem::getOutputForAttr(attr, &output,
+                                                    (audio_session_t)mSessionId, &streamType,
+                                                    mSampleRate, mFormat, mChannelMask,
+                                                    mFlags, mOffloadInfo);
+
+
+    if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
         ALOGE("Could not get audio output for stream type %d, usage %d, sample rate %u, format %#x,"
               " channel mask %#x, flags %#x",
-              mStreamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags);
+              streamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags);
         return BAD_VALUE;
     }
     {
@@ -963,7 +995,9 @@
         ALOGE("getSamplingRate(output=%d) status %d", output, status);
         goto release;
     }
-
+    if (mSampleRate == 0) {
+        mSampleRate = afSampleRate;
+    }
     // Client decides whether the track is TIMED (see below), but can only express a preference
     // for FAST.  Server will perform additional tests.
     if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) && !((
@@ -971,7 +1005,9 @@
             // use case 1: shared buffer
             (mSharedBuffer != 0) ||
             // use case 2: callback transfer mode
-            (mTransfer == TRANSFER_CALLBACK)) &&
+            (mTransfer == TRANSFER_CALLBACK) ||
+            // use case 3: obtain/release mode
+            (mTransfer == TRANSFER_OBTAIN)) &&
             // matching sample rate
             (mSampleRate == afSampleRate))) {
         ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client");
@@ -983,11 +1019,9 @@
     // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where
     //  n = 1   fast track with single buffering; nBuffering is ignored
     //  n = 2   fast track with double buffering
-    //  n = 2   normal track, no sample rate conversion
-    //  n = 3   normal track, with sample rate conversion
-    //          (pessimistic; some non-1:1 conversion ratios don't actually need triple-buffering)
-    //  n > 3   very high latency or very small notification interval; nBuffering is ignored
-    const uint32_t nBuffering = (mSampleRate == afSampleRate) ? 2 : 3;
+    //  n = 2   normal track, (including those with sample rate conversion)
+    //  n >= 3  very high latency or very small notification interval (unused).
+    const uint32_t nBuffering = 2;
 
     mNotificationFramesAct = mNotificationFramesReq;
 
@@ -1004,12 +1038,12 @@
             mNotificationFramesAct = frameCount;
         }
     } else if (mSharedBuffer != 0) {
-
-        // Ensure that buffer alignment matches channel count
-        // 8-bit data in shared memory is not currently supported by AudioFlinger
-        size_t alignment = audio_bytes_per_sample(
-                mFormat == AUDIO_FORMAT_PCM_8_BIT ? AUDIO_FORMAT_PCM_16_BIT : mFormat);
+        // FIXME: Ensure client side memory buffers need
+        // not have additional alignment beyond sample
+        // (e.g. 16 bit stereo accessed as 32 bit frame).
+        size_t alignment = audio_bytes_per_sample(mFormat);
         if (alignment & 1) {
+            // for AUDIO_FORMAT_PCM_24_BIT_PACKED (not exposed through Java).
             alignment = 1;
         }
         if (mChannelCount > 1) {
@@ -1027,40 +1061,10 @@
         // there's no frameCount parameter.
         // But when initializing a shared buffer AudioTrack via set(),
         // there _is_ a frameCount parameter.  We silently ignore it.
-        frameCount = mSharedBuffer->size() / mFrameSizeAF;
-
-    } else if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
-
-        // FIXME move these calculations and associated checks to server
-
-        // Ensure that buffer depth covers at least audio hardware latency
-        uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
-        ALOGV("afFrameCount=%zu, minBufCount=%d, afSampleRate=%u, afLatency=%d",
-                afFrameCount, minBufCount, afSampleRate, afLatency);
-        if (minBufCount <= nBuffering) {
-            minBufCount = nBuffering;
-        }
-
-        size_t minFrameCount = afFrameCount * minBufCount * uint64_t(mSampleRate) / afSampleRate;
-        ALOGV("minFrameCount: %zu, afFrameCount=%zu, minBufCount=%d, sampleRate=%u, afSampleRate=%u"
-                ", afLatency=%d",
-                minFrameCount, afFrameCount, minBufCount, mSampleRate, afSampleRate, afLatency);
-
-        if (frameCount == 0) {
-            frameCount = minFrameCount;
-        } else if (frameCount < minFrameCount) {
-            // not ALOGW because it happens all the time when playing key clicks over A2DP
-            ALOGV("Minimum buffer size corrected from %zu to %zu",
-                     frameCount, minFrameCount);
-            frameCount = minFrameCount;
-        }
-        // Make sure that application is notified with sufficient margin before underrun
-        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
-            mNotificationFramesAct = frameCount/nBuffering;
-        }
-
+        frameCount = mSharedBuffer->size() / mFrameSize;
     } else {
-        // For fast tracks, the frame count calculations and checks are done by server
+        // For fast and normal streaming tracks,
+        // the frame count calculations and checks are done by server
     }
 
     IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT;
@@ -1086,12 +1090,9 @@
 
     size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
                                 // but we will still need the original value also
-    sp<IAudioTrack> track = audioFlinger->createTrack(mStreamType,
+    sp<IAudioTrack> track = audioFlinger->createTrack(streamType,
                                                       mSampleRate,
-                                                      // AudioFlinger only sees 16-bit PCM
-                                                      mFormat == AUDIO_FORMAT_PCM_8_BIT &&
-                                                          !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT) ?
-                                                              AUDIO_FORMAT_PCM_16_BIT : mFormat,
+                                                      mFormat,
                                                       mChannelMask,
                                                       &temp,
                                                       &trackFlags,
@@ -1123,7 +1124,7 @@
     }
     // invariant that mAudioTrack != 0 is true only after set() returns successfully
     if (mAudioTrack != 0) {
-        mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this);
+        IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
         mDeathNotifier.clear();
     }
     mAudioTrack = track;
@@ -1146,23 +1147,10 @@
         if (trackFlags & IAudioFlinger::TRACK_FAST) {
             ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu", frameCount);
             mAwaitBoost = true;
-            if (mSharedBuffer == 0) {
-                // Theoretically double-buffering is not required for fast tracks,
-                // due to tighter scheduling.  But in practice, to accommodate kernels with
-                // scheduling jitter, and apps with computation jitter, we use double-buffering.
-                if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
-                    mNotificationFramesAct = frameCount/nBuffering;
-                }
-            }
         } else {
             ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
             // once denied, do not request again if IAudioTrack is re-created
             mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
-            if (mSharedBuffer == 0) {
-                if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
-                    mNotificationFramesAct = frameCount/nBuffering;
-                }
-            }
         }
     }
     if (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
@@ -1185,6 +1173,16 @@
             //return NO_INIT;
         }
     }
+    // Make sure that application is notified with sufficient margin before underrun
+    if (mSharedBuffer == 0 && audio_is_linear_pcm(mFormat)) {
+        // Theoretically double-buffering is not required for fast tracks,
+        // due to tighter scheduling.  But in practice, to accommodate kernels with
+        // scheduling jitter, and apps with computation jitter, we use double-buffering
+        // for fast tracks just like normal streaming tracks.
+        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount / nBuffering) {
+            mNotificationFramesAct = frameCount / nBuffering;
+        }
+    }
 
     // We retain a copy of the I/O handle, but don't own the reference
     mOutput = output;
@@ -1215,31 +1213,35 @@
     // update proxy
     if (mSharedBuffer == 0) {
         mStaticProxy.clear();
-        mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF);
+        mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
     } else {
-        mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF);
+        mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSize);
         mProxy = mStaticProxy;
     }
-    mProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
+
+    mProxy->setVolumeLR(gain_minifloat_pack(
+            gain_from_float(mVolume[AUDIO_INTERLEAVE_LEFT]),
+            gain_from_float(mVolume[AUDIO_INTERLEAVE_RIGHT])));
+
     mProxy->setSendLevel(mSendLevel);
     mProxy->setSampleRate(mSampleRate);
     mProxy->setMinimum(mNotificationFramesAct);
 
     mDeathNotifier = new DeathNotifier(this);
-    mAudioTrack->asBinder()->linkToDeath(mDeathNotifier, this);
+    IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this);
 
     return NO_ERROR;
     }
 
 release:
-    AudioSystem::releaseOutput(output);
+    AudioSystem::releaseOutput(output, streamType, (audio_session_t)mSessionId);
     if (status == NO_ERROR) {
         status = NO_INIT;
     }
     return status;
 }
 
-status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
+status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount, size_t *nonContig)
 {
     if (audioBuffer == NULL) {
         return BAD_VALUE;
@@ -1266,7 +1268,7 @@
         ALOGE("%s invalid waitCount %d", __func__, waitCount);
         requested = NULL;
     }
-    return obtainBuffer(audioBuffer, requested);
+    return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig);
 }
 
 status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
@@ -1333,7 +1335,7 @@
     } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
 
     audioBuffer->frameCount = buffer.mFrameCount;
-    audioBuffer->size = buffer.mFrameCount * mFrameSizeAF;
+    audioBuffer->size = buffer.mFrameCount * mFrameSize;
     audioBuffer->raw = buffer.mRaw;
     if (nonContig != NULL) {
         *nonContig = buffer.mNonContig;
@@ -1341,13 +1343,14 @@
     return status;
 }
 
-void AudioTrack::releaseBuffer(Buffer* audioBuffer)
+void AudioTrack::releaseBuffer(const Buffer* audioBuffer)
 {
+    // FIXME add error checking on mode, by adding an internal version
     if (mTransfer == TRANSFER_SHARED) {
         return;
     }
 
-    size_t stepCount = audioBuffer->size / mFrameSizeAF;
+    size_t stepCount = audioBuffer->size / mFrameSize;
     if (stepCount == 0) {
         return;
     }
@@ -1413,14 +1416,8 @@
         }
 
         size_t toWrite;
-        if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
-            // Divide capacity by 2 to take expansion into account
-            toWrite = audioBuffer.size >> 1;
-            memcpy_to_i16_from_u8(audioBuffer.i16, (const uint8_t *) buffer, toWrite);
-        } else {
-            toWrite = audioBuffer.size;
-            memcpy(audioBuffer.i8, buffer, toWrite);
-        }
+        toWrite = audioBuffer.size;
+        memcpy(audioBuffer.i8, buffer, toWrite);
         buffer = ((const char *) buffer) + toWrite;
         userSize -= toWrite;
         written += toWrite;
@@ -1540,9 +1537,8 @@
         // that the upper layers can recreate the track
         if (!isOffloadedOrDirect_l() || (mSequence == mObservedSequence)) {
             status_t status = restoreTrack_l("processAudioBuffer");
-            mLock.unlock();
-            // Run again immediately, but with a new IAudioTrack
-            return 0;
+            // after restoration, continue below to make sure that the loop and buffer events
+            // are notified because they have been cleared from mCblk->mFlags above.
         }
     }
 
@@ -1591,7 +1587,6 @@
     }
 
     // Cache other fields that will be needed soon
-    uint32_t loopPeriod = mLoopPeriod;
     uint32_t sampleRate = mSampleRate;
     uint32_t notificationFrames = mNotificationFramesAct;
     if (mRefreshRemaining) {
@@ -1603,8 +1598,30 @@
     uint32_t sequence = mSequence;
     sp<AudioTrackClientProxy> proxy = mProxy;
 
+    // Determine the number of new loop callback(s) that will be needed, while locked.
+    int loopCountNotifications = 0;
+    uint32_t loopPeriod = 0; // time in frames for next EVENT_LOOP_END or EVENT_BUFFER_END
+
+    if (mLoopCount > 0) {
+        int loopCount;
+        size_t bufferPosition;
+        mStaticProxy->getBufferPositionAndLoopCount(&bufferPosition, &loopCount);
+        loopPeriod = ((loopCount > 0) ? mLoopEnd : mFrameCount) - bufferPosition;
+        loopCountNotifications = min(mLoopCountNotified - loopCount, kMaxLoopCountNotifications);
+        mLoopCountNotified = loopCount; // discard any excess notifications
+    } else if (mLoopCount < 0) {
+        // FIXME: We're not accurate with notification count and position with infinite looping
+        // since loopCount from server side will always return -1 (we could decrement it).
+        size_t bufferPosition = mStaticProxy->getBufferPosition();
+        loopCountNotifications = int((flags & (CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL)) != 0);
+        loopPeriod = mLoopEnd - bufferPosition;
+    } else if (/* mLoopCount == 0 && */ mSharedBuffer != 0) {
+        size_t bufferPosition = mStaticProxy->getBufferPosition();
+        loopPeriod = mFrameCount - bufferPosition;
+    }
+
     // These fields don't need to be cached, because they are assigned only by set():
-    //     mTransfer, mCbf, mUserData, mFormat, mFrameSize, mFrameSizeAF, mFlags
+    //     mTransfer, mCbf, mUserData, mFormat, mFrameSize, mFlags
     // mFlags is also assigned by createTrack_l(), but not the bit we care about.
 
     mLock.unlock();
@@ -1643,10 +1660,9 @@
     if (newUnderrun) {
         mCbf(EVENT_UNDERRUN, mUserData, NULL);
     }
-    // FIXME we will miss loops if loop cycle was signaled several times since last call
-    //       to processAudioBuffer()
-    if (flags & (CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL)) {
+    while (loopCountNotifications > 0) {
         mCbf(EVENT_LOOP_END, mUserData, NULL);
+        --loopCountNotifications;
     }
     if (flags & CBLK_BUFFER_END) {
         mCbf(EVENT_BUFFER_END, mUserData, NULL);
@@ -1682,10 +1698,11 @@
         minFrames = markerPosition - position;
     }
     if (loopPeriod > 0 && loopPeriod < minFrames) {
+        // loopPeriod is already adjusted for actual position.
         minFrames = loopPeriod;
     }
-    if (updatePeriod > 0 && updatePeriod < minFrames) {
-        minFrames = updatePeriod;
+    if (updatePeriod > 0) {
+        minFrames = min(minFrames, uint32_t(newPosition - position));
     }
 
     // If > 0, poll periodically to recover from a stuck server.  A good value is 2.
@@ -1748,13 +1765,6 @@
             }
         }
 
-        // Divide buffer size by 2 to take into account the expansion
-        // due to 8 to 16 bit conversion: the callback must fill only half
-        // of the destination buffer
-        if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
-            audioBuffer.size >>= 1;
-        }
-
         size_t reqSize = audioBuffer.size;
         mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
         size_t writtenSize = audioBuffer.size;
@@ -1774,13 +1784,7 @@
             return WAIT_PERIOD_MS * 1000000LL;
         }
 
-        if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
-            // 8 to 16 bit conversion, note that source and destination are the same address
-            memcpy_to_i16_from_u8(audioBuffer.i16, (const uint8_t *) audioBuffer.i8, writtenSize);
-            audioBuffer.size <<= 1;
-        }
-
-        size_t releasedFrames = audioBuffer.size / mFrameSizeAF;
+        size_t releasedFrames = audioBuffer.size / mFrameSize;
         audioBuffer.frameCount = releasedFrames;
         mRemainingFrames -= releasedFrames;
         if (misalignment >= releasedFrames) {
@@ -1828,7 +1832,7 @@
     status_t result;
 
     // refresh the audio configuration cache in this process to make sure we get new
-    // output parameters in createTrack_l()
+    // output parameters and new IAudioFlinger in createTrack_l()
     AudioSystem::clearAudioConfigCache();
 
     if (isOffloadedOrDirect_l()) {
@@ -1837,7 +1841,11 @@
     }
 
     // save the old static buffer position
-    size_t bufferPosition = mStaticProxy != NULL ? mStaticProxy->getBufferPosition() : 0;
+    size_t bufferPosition = 0;
+    int loopCount = 0;
+    if (mStaticProxy != 0) {
+        mStaticProxy->getBufferPositionAndLoopCount(&bufferPosition, &loopCount);
+    }
 
     // If a new IAudioTrack is successfully created, createTrack_l() will modify the
     // following member variables: mAudioTrack, mCblkMemory and mCblk.
@@ -1846,30 +1854,26 @@
     result = createTrack_l();
 
     // take the frames that will be lost by track recreation into account in saved position
+    // For streaming tracks, this is the amount we obtained from the user/client
+    // (not the number actually consumed at the server - those are already lost).
     (void) updateAndGetPosition_l();
-    mPosition = mReleased;
+    if (mStaticProxy != 0) {
+        mPosition = mReleased;
+    }
 
     if (result == NO_ERROR) {
-        // continue playback from last known position, but
-        // don't attempt to restore loop after invalidation; it's difficult and not worthwhile
-        if (mStaticProxy != NULL) {
-            mLoopPeriod = 0;
-            mStaticProxy->setLoop(bufferPosition, mFrameCount, 0);
-        }
-        // FIXME How do we simulate the fact that all frames present in the buffer at the time of
-        //       track destruction have been played? This is critical for SoundPool implementation
-        //       This must be broken, and needs to be tested/debugged.
-#if 0
-        // restore write index and set other indexes to reflect empty buffer status
-        if (!strcmp(from, "start")) {
-            // Make sure that a client relying on callback events indicating underrun or
-            // the actual amount of audio frames played (e.g SoundPool) receives them.
-            if (mSharedBuffer == 0) {
-                // restart playback even if buffer is not completely filled.
-                android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags);
+        // Continue playback from last known position and restore loop.
+        if (mStaticProxy != 0) {
+            if (loopCount != 0) {
+                mStaticProxy->setBufferPositionAndLoop(bufferPosition,
+                        mLoopStart, mLoopEnd, loopCount);
+            } else {
+                mStaticProxy->setBufferPosition(bufferPosition);
+                if (bufferPosition == mFrameCount) {
+                    ALOGD("restoring track at end of static buffer");
+                }
             }
         }
-#endif
         if (mState == STATE_ACTIVE) {
             result = mAudioTrack->start();
         }
@@ -1936,6 +1940,10 @@
         break;
     }
 
+    if (mCblk->mFlags & CBLK_INVALID) {
+        restoreTrack_l("getTimestamp");
+    }
+
     // The presented frame count must always lag behind the consumed frame count.
     // To avoid a race, read the presented frames first.  This ensures that presented <= consumed.
     status_t status = mAudioTrack->getTimestamp(timestamp);
@@ -2066,156 +2074,6 @@
     return mProxy->getUnderrunFrames();
 }
 
-void AudioTrack::setAttributesFromStreamType(audio_stream_type_t streamType) {
-    mAttributes.flags = 0x0;
-
-    switch(streamType) {
-    case AUDIO_STREAM_DEFAULT:
-    case AUDIO_STREAM_MUSIC:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
-        mAttributes.usage = AUDIO_USAGE_MEDIA;
-        break;
-    case AUDIO_STREAM_VOICE_CALL:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
-        mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
-        break;
-    case AUDIO_STREAM_ENFORCED_AUDIBLE:
-        mAttributes.flags  |= AUDIO_FLAG_AUDIBILITY_ENFORCED;
-        // intended fall through, attributes in common with STREAM_SYSTEM
-    case AUDIO_STREAM_SYSTEM:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
-        mAttributes.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
-        break;
-    case AUDIO_STREAM_RING:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
-        mAttributes.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
-        break;
-    case AUDIO_STREAM_ALARM:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
-        mAttributes.usage = AUDIO_USAGE_ALARM;
-        break;
-    case AUDIO_STREAM_NOTIFICATION:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
-        mAttributes.usage = AUDIO_USAGE_NOTIFICATION;
-        break;
-    case AUDIO_STREAM_BLUETOOTH_SCO:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
-        mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
-        mAttributes.flags |= AUDIO_FLAG_SCO;
-        break;
-    case AUDIO_STREAM_DTMF:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
-        mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
-        break;
-    case AUDIO_STREAM_TTS:
-        mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
-        mAttributes.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
-        break;
-    default:
-        ALOGE("invalid stream type %d when converting to attributes", streamType);
-    }
-}
-
-void AudioTrack::setStreamTypeFromAttributes(audio_attributes_t& aa) {
-    // flags to stream type mapping
-    if ((aa.flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
-        mStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE;
-        return;
-    }
-    if ((aa.flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) {
-        mStreamType = AUDIO_STREAM_BLUETOOTH_SCO;
-        return;
-    }
-    // TODO once AudioPolicyManager fully supports audio_attributes_t,
-    //   remove stream remap, the flag will be enough
-    if ((aa.flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) {
-        mStreamType = AUDIO_STREAM_TTS;
-        return;
-    }
-
-    // usage to stream type mapping
-    switch (aa.usage) {
-    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: {
-        // TODO once AudioPolicyManager fully supports audio_attributes_t,
-        //   remove stream change based on stream activity
-        bool active;
-        status_t status = AudioSystem::isStreamActive(AUDIO_STREAM_RING, &active, 0);
-        if (status == NO_ERROR && active == true) {
-            mStreamType = AUDIO_STREAM_RING;
-            break;
-        }
-        status = AudioSystem::isStreamActive(AUDIO_STREAM_ALARM, &active, 0);
-        if (status == NO_ERROR && active == true) {
-            mStreamType = AUDIO_STREAM_ALARM;
-            break;
-        }
-    }    /// FALL THROUGH
-    case AUDIO_USAGE_MEDIA:
-    case AUDIO_USAGE_GAME:
-    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
-        mStreamType = AUDIO_STREAM_MUSIC;
-        return;
-    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
-        mStreamType = AUDIO_STREAM_SYSTEM;
-        return;
-    case AUDIO_USAGE_VOICE_COMMUNICATION:
-        mStreamType = AUDIO_STREAM_VOICE_CALL;
-        return;
-
-    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
-        mStreamType = AUDIO_STREAM_DTMF;
-        return;
-
-    case AUDIO_USAGE_ALARM:
-        mStreamType = AUDIO_STREAM_ALARM;
-        return;
-    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
-        mStreamType = AUDIO_STREAM_RING;
-        return;
-
-    case AUDIO_USAGE_NOTIFICATION:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
-    case AUDIO_USAGE_NOTIFICATION_EVENT:
-        mStreamType = AUDIO_STREAM_NOTIFICATION;
-        return;
-
-    case AUDIO_USAGE_UNKNOWN:
-    default:
-        mStreamType = AUDIO_STREAM_MUSIC;
-    }
-}
-
-bool AudioTrack::isValidAttributes(const audio_attributes_t *paa) {
-    // has flags that map to a strategy?
-    if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) {
-        return true;
-    }
-
-    // has known usage?
-    switch (paa->usage) {
-    case AUDIO_USAGE_UNKNOWN:
-    case AUDIO_USAGE_MEDIA:
-    case AUDIO_USAGE_VOICE_COMMUNICATION:
-    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
-    case AUDIO_USAGE_ALARM:
-    case AUDIO_USAGE_NOTIFICATION:
-    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
-    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
-    case AUDIO_USAGE_NOTIFICATION_EVENT:
-    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
-    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
-    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
-    case AUDIO_USAGE_GAME:
-        break;
-    default:
-        return false;
-    }
-    return true;
-}
 // =========================================================================
 
 void AudioTrack::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
@@ -2275,8 +2133,8 @@
     case NS_NEVER:
         return false;
     case NS_WHENEVER:
-        // FIXME increase poll interval, or make event-driven
-        ns = 1000000000LL;
+        // Event driven: call wake() when callback notifications conditions change.
+        ns = INT64_MAX;
         // fall through
     default:
         LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns);
@@ -2309,6 +2167,17 @@
     }
 }
 
+void AudioTrack::AudioTrackThread::wake()
+{
+    AutoMutex _l(mMyLock);
+    if (!mPaused && mPausedInt && mPausedNs > 0) {
+        // audio track is active and internally paused with timeout.
+        mIgnoreNextPausedInt = true;
+        mPausedInt = false;
+        mMyCond.signal();
+    }
+}
+
 void AudioTrack::AudioTrackThread::pauseInternal(nsecs_t ns)
 {
     AutoMutex _l(mMyLock);
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 561cb24..6d5f1af 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -25,6 +25,26 @@
 
 namespace android {
 
+// used to clamp a value to size_t.  TODO: move to another file.
+template <typename T>
+size_t clampToSize(T x) {
+    return sizeof(T) > sizeof(size_t) && x > (T) SIZE_MAX ? SIZE_MAX : x < 0 ? 0 : (size_t) x;
+}
+
+// incrementSequence is used to determine the next sequence value
+// for the loop and position sequence counters.  It should return
+// a value between "other" + 1 and "other" + INT32_MAX, the choice of
+// which needs to be the "least recently used" sequence value for "self".
+// In general, this means (new_self) returned is max(self, other) + 1.
+
+static uint32_t incrementSequence(uint32_t self, uint32_t other) {
+    int32_t diff = self - other;
+    if (diff >= 0 && diff < INT32_MAX) {
+        return self + 1; // we're already ahead of other.
+    }
+    return other + 1; // we're behind, so move just ahead of other.
+}
+
 audio_track_cblk_t::audio_track_cblk_t()
     : mServer(0), mFutex(0), mMinimum(0),
     mVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY), mSampleRate(0), mSendLevel(0), mFlags(0)
@@ -301,6 +321,7 @@
 {
     audio_track_cblk_t* cblk = mCblk;
     if (!(android_atomic_or(CBLK_INVALID, &cblk->mFlags) & CBLK_INVALID)) {
+        android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
         // it seems that a FUTEX_WAKE_PRIVATE will not wake a FUTEX_WAIT, even within same process
         (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
                 1);
@@ -311,6 +332,7 @@
 {
     audio_track_cblk_t* cblk = mCblk;
     if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->mFlags) & CBLK_INTERRUPT)) {
+        android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
         (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
                 1);
     }
@@ -401,7 +423,6 @@
             goto end;
         }
         // check for obtainBuffer interrupted by client
-        // check for obtainBuffer interrupted by client
         if (flags & CBLK_INTERRUPT) {
             ALOGV("waitStreamEndDone() interrupted by client");
             status = -EINTR;
@@ -477,8 +498,11 @@
 StaticAudioTrackClientProxy::StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers,
         size_t frameCount, size_t frameSize)
     : AudioTrackClientProxy(cblk, buffers, frameCount, frameSize),
-      mMutator(&cblk->u.mStatic.mSingleStateQueue), mBufferPosition(0)
+      mMutator(&cblk->u.mStatic.mSingleStateQueue),
+      mPosLoopObserver(&cblk->u.mStatic.mPosLoopQueue)
 {
+    memset(&mState, 0, sizeof(mState));
+    memset(&mPosLoop, 0, sizeof(mPosLoop));
 }
 
 void StaticAudioTrackClientProxy::flush()
@@ -493,26 +517,72 @@
         // FIXME Should return an error status
         return;
     }
-    StaticAudioTrackState newState;
-    newState.mLoopStart = (uint32_t) loopStart;
-    newState.mLoopEnd = (uint32_t) loopEnd;
-    newState.mLoopCount = loopCount;
-    mBufferPosition = loopStart;
-    (void) mMutator.push(newState);
+    mState.mLoopStart = (uint32_t) loopStart;
+    mState.mLoopEnd = (uint32_t) loopEnd;
+    mState.mLoopCount = loopCount;
+    mState.mLoopSequence = incrementSequence(mState.mLoopSequence, mState.mPositionSequence);
+    // set patch-up variables until the mState is acknowledged by the ServerProxy.
+    // observed buffer position and loop count will freeze until then to give the
+    // illusion of a synchronous change.
+    getBufferPositionAndLoopCount(NULL, NULL);
+    // preserve behavior to restart at mState.mLoopStart if position exceeds mState.mLoopEnd.
+    if (mState.mLoopCount != 0 && mPosLoop.mBufferPosition >= mState.mLoopEnd) {
+        mPosLoop.mBufferPosition = mState.mLoopStart;
+    }
+    mPosLoop.mLoopCount = mState.mLoopCount;
+    (void) mMutator.push(mState);
+}
+
+void StaticAudioTrackClientProxy::setBufferPosition(size_t position)
+{
+    // This can only happen on a 64-bit client
+    if (position > UINT32_MAX) {
+        // FIXME Should return an error status
+        return;
+    }
+    mState.mPosition = (uint32_t) position;
+    mState.mPositionSequence = incrementSequence(mState.mPositionSequence, mState.mLoopSequence);
+    // set patch-up variables until the mState is acknowledged by the ServerProxy.
+    // observed buffer position and loop count will freeze until then to give the
+    // illusion of a synchronous change.
+    if (mState.mLoopCount > 0) {  // only check if loop count is changing
+        getBufferPositionAndLoopCount(NULL, NULL); // get last position
+    }
+    mPosLoop.mBufferPosition = position;
+    if (position >= mState.mLoopEnd) {
+        // no ongoing loop is possible if position is greater than loopEnd.
+        mPosLoop.mLoopCount = 0;
+    }
+    (void) mMutator.push(mState);
+}
+
+void StaticAudioTrackClientProxy::setBufferPositionAndLoop(size_t position, size_t loopStart,
+        size_t loopEnd, int loopCount)
+{
+    setLoop(loopStart, loopEnd, loopCount);
+    setBufferPosition(position);
 }
 
 size_t StaticAudioTrackClientProxy::getBufferPosition()
 {
-    size_t bufferPosition;
-    if (mMutator.ack()) {
-        bufferPosition = (size_t) mCblk->u.mStatic.mBufferPosition;
-        if (bufferPosition > mFrameCount) {
-            bufferPosition = mFrameCount;
-        }
-    } else {
-        bufferPosition = mBufferPosition;
+    getBufferPositionAndLoopCount(NULL, NULL);
+    return mPosLoop.mBufferPosition;
+}
+
+void StaticAudioTrackClientProxy::getBufferPositionAndLoopCount(
+        size_t *position, int *loopCount)
+{
+    if (mMutator.ack() == StaticAudioTrackSingleStateQueue::SSQ_DONE) {
+         if (mPosLoopObserver.poll(mPosLoop)) {
+             ; // a valid mPosLoop should be available if ackDone is true.
+         }
     }
-    return bufferPosition;
+    if (position != NULL) {
+        *position = mPosLoop.mBufferPosition;
+    }
+    if (loopCount != NULL) {
+        *loopCount = mPosLoop.mLoopCount;
+    }
 }
 
 // ---------------------------------------------------------------------------
@@ -548,7 +618,8 @@
             ssize_t filled = rear - newFront;
             // Rather than shutting down on a corrupt flush, just treat it as a full flush
             if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
-                ALOGE("mFlush %#x -> %#x, front %#x, rear %#x, mask %#x, newFront %#x, filled %d=%#x",
+                ALOGE("mFlush %#x -> %#x, front %#x, rear %#x, mask %#x, newFront %#x, "
+                        "filled %d=%#x",
                         mFlush, flush, front, rear, mask, newFront, filled, filled);
                 newFront = rear;
             }
@@ -727,12 +798,12 @@
 StaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers,
         size_t frameCount, size_t frameSize)
     : AudioTrackServerProxy(cblk, buffers, frameCount, frameSize),
-      mObserver(&cblk->u.mStatic.mSingleStateQueue), mPosition(0),
-      mEnd(frameCount), mFramesReadyIsCalledByMultipleThreads(false)
+      mObserver(&cblk->u.mStatic.mSingleStateQueue),
+      mPosLoopMutator(&cblk->u.mStatic.mPosLoopQueue),
+      mFramesReadySafe(frameCount), mFramesReady(frameCount),
+      mFramesReadyIsCalledByMultipleThreads(false)
 {
-    mState.mLoopStart = 0;
-    mState.mLoopEnd = 0;
-    mState.mLoopCount = 0;
+    memset(&mState, 0, sizeof(mState));
 }
 
 void StaticAudioTrackServerProxy::framesReadyIsCalledByMultipleThreads()
@@ -742,59 +813,104 @@
 
 size_t StaticAudioTrackServerProxy::framesReady()
 {
-    // FIXME
-    // This is racy if called by normal mixer thread,
-    // as we're reading 2 independent variables without a lock.
-    // Can't call mObserver.poll(), as we might be called from wrong thread.
-    // If looping is enabled, should return a higher number (since includes non-contiguous).
-    size_t position = mPosition;
+    // Can't call pollPosition() from multiple threads.
     if (!mFramesReadyIsCalledByMultipleThreads) {
-        ssize_t positionOrStatus = pollPosition();
-        if (positionOrStatus >= 0) {
-            position = (size_t) positionOrStatus;
-        }
+        (void) pollPosition();
     }
-    size_t end = mEnd;
-    return position < end ? end - position : 0;
+    return mFramesReadySafe;
+}
+
+status_t StaticAudioTrackServerProxy::updateStateWithLoop(
+        StaticAudioTrackState *localState, const StaticAudioTrackState &update) const
+{
+    if (localState->mLoopSequence != update.mLoopSequence) {
+        bool valid = false;
+        const size_t loopStart = update.mLoopStart;
+        const size_t loopEnd = update.mLoopEnd;
+        size_t position = localState->mPosition;
+        if (update.mLoopCount == 0) {
+            valid = true;
+        } else if (update.mLoopCount >= -1) {
+            if (loopStart < loopEnd && loopEnd <= mFrameCount &&
+                    loopEnd - loopStart >= MIN_LOOP) {
+                // If the current position is greater than the end of the loop
+                // we "wrap" to the loop start. This might cause an audible pop.
+                if (position >= loopEnd) {
+                    position = loopStart;
+                }
+                valid = true;
+            }
+        }
+        if (!valid || position > mFrameCount) {
+            return NO_INIT;
+        }
+        localState->mPosition = position;
+        localState->mLoopCount = update.mLoopCount;
+        localState->mLoopEnd = loopEnd;
+        localState->mLoopStart = loopStart;
+        localState->mLoopSequence = update.mLoopSequence;
+    }
+    return OK;
+}
+
+status_t StaticAudioTrackServerProxy::updateStateWithPosition(
+        StaticAudioTrackState *localState, const StaticAudioTrackState &update) const
+{
+    if (localState->mPositionSequence != update.mPositionSequence) {
+        if (update.mPosition > mFrameCount) {
+            return NO_INIT;
+        } else if (localState->mLoopCount != 0 && update.mPosition >= localState->mLoopEnd) {
+            localState->mLoopCount = 0; // disable loop count if position is beyond loop end.
+        }
+        localState->mPosition = update.mPosition;
+        localState->mPositionSequence = update.mPositionSequence;
+    }
+    return OK;
 }
 
 ssize_t StaticAudioTrackServerProxy::pollPosition()
 {
-    size_t position = mPosition;
     StaticAudioTrackState state;
     if (mObserver.poll(state)) {
-        bool valid = false;
-        size_t loopStart = state.mLoopStart;
-        size_t loopEnd = state.mLoopEnd;
-        if (state.mLoopCount == 0) {
-            if (loopStart > mFrameCount) {
-                loopStart = mFrameCount;
-            }
-            // ignore loopEnd
-            mPosition = position = loopStart;
-            mEnd = mFrameCount;
-            mState.mLoopCount = 0;
-            valid = true;
+        StaticAudioTrackState trystate = mState;
+        bool result;
+        const int32_t diffSeq = state.mLoopSequence - state.mPositionSequence;
+
+        if (diffSeq < 0) {
+            result = updateStateWithLoop(&trystate, state) == OK &&
+                    updateStateWithPosition(&trystate, state) == OK;
         } else {
-            if (loopStart < loopEnd && loopEnd <= mFrameCount &&
-                    loopEnd - loopStart >= MIN_LOOP) {
-                if (!(loopStart <= position && position < loopEnd)) {
-                    mPosition = position = loopStart;
-                }
-                mEnd = loopEnd;
-                mState = state;
-                valid = true;
-            }
+            result = updateStateWithPosition(&trystate, state) == OK &&
+                    updateStateWithLoop(&trystate, state) == OK;
         }
-        if (!valid) {
+        if (!result) {
+            mObserver.done();
+            // caution: no update occurs so server state will be inconsistent with client state.
             ALOGE("%s client pushed an invalid state, shutting down", __func__);
             mIsShutdown = true;
             return (ssize_t) NO_INIT;
         }
+        mState = trystate;
+        if (mState.mLoopCount == -1) {
+            mFramesReady = INT64_MAX;
+        } else if (mState.mLoopCount == 0) {
+            mFramesReady = mFrameCount - mState.mPosition;
+        } else if (mState.mLoopCount > 0) {
+            // TODO: Later consider fixing overflow, but does not seem needed now
+            // as will not overflow if loopStart and loopEnd are Java "ints".
+            mFramesReady = int64_t(mState.mLoopCount) * (mState.mLoopEnd - mState.mLoopStart)
+                    + mFrameCount - mState.mPosition;
+        }
+        mFramesReadySafe = clampToSize(mFramesReady);
         // This may overflow, but client is not supposed to rely on it
-        mCblk->u.mStatic.mBufferPosition = (uint32_t) position;
+        StaticAudioTrackPosLoop posLoop;
+
+        posLoop.mLoopCount = (int32_t) mState.mLoopCount;
+        posLoop.mBufferPosition = (uint32_t) mState.mPosition;
+        mPosLoopMutator.push(posLoop);
+        mObserver.done(); // safe to read mStatic variables.
     }
-    return (ssize_t) position;
+    return (ssize_t) mState.mPosition;
 }
 
 status_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush __unused)
@@ -815,9 +931,10 @@
         return (status_t) positionOrStatus;
     }
     size_t position = (size_t) positionOrStatus;
+    size_t end = mState.mLoopCount != 0 ? mState.mLoopEnd : mFrameCount;
     size_t avail;
-    if (position < mEnd) {
-        avail = mEnd - position;
+    if (position < end) {
+        avail = end - position;
         size_t wanted = buffer->mFrameCount;
         if (avail < wanted) {
             buffer->mFrameCount = avail;
@@ -830,7 +947,10 @@
         buffer->mFrameCount = 0;
         buffer->mRaw = NULL;
     }
-    buffer->mNonContig = 0;     // FIXME should be > 0 for looping
+    // As mFramesReady is the total remaining frames in the static audio track,
+    // it is always larger or equal to avail.
+    LOG_ALWAYS_FATAL_IF(mFramesReady < (int64_t) avail);
+    buffer->mNonContig = mFramesReady == INT64_MAX ? SIZE_MAX : clampToSize(mFramesReady - avail);
     mUnreleased = avail;
     return NO_ERROR;
 }
@@ -838,6 +958,7 @@
 void StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer)
 {
     size_t stepCount = buffer->mFrameCount;
+    LOG_ALWAYS_FATAL_IF(!((int64_t) stepCount <= mFramesReady));
     LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased));
     if (stepCount == 0) {
         // prevent accidental re-use of buffer
@@ -847,29 +968,36 @@
     }
     mUnreleased -= stepCount;
     audio_track_cblk_t* cblk = mCblk;
-    size_t position = mPosition;
+    size_t position = mState.mPosition;
     size_t newPosition = position + stepCount;
     int32_t setFlags = 0;
     if (!(position <= newPosition && newPosition <= mFrameCount)) {
-        ALOGW("%s newPosition %zu outside [%zu, %zu]", __func__, newPosition, position, mFrameCount);
+        ALOGW("%s newPosition %zu outside [%zu, %zu]", __func__, newPosition, position,
+                mFrameCount);
         newPosition = mFrameCount;
     } else if (mState.mLoopCount != 0 && newPosition == mState.mLoopEnd) {
+        newPosition = mState.mLoopStart;
         if (mState.mLoopCount == -1 || --mState.mLoopCount != 0) {
-            newPosition = mState.mLoopStart;
             setFlags = CBLK_LOOP_CYCLE;
         } else {
-            mEnd = mFrameCount;     // this is what allows playback to continue after the loop
             setFlags = CBLK_LOOP_FINAL;
         }
     }
     if (newPosition == mFrameCount) {
         setFlags |= CBLK_BUFFER_END;
     }
-    mPosition = newPosition;
+    mState.mPosition = newPosition;
+    if (mFramesReady != INT64_MAX) {
+        mFramesReady -= stepCount;
+    }
+    mFramesReadySafe = clampToSize(mFramesReady);
 
     cblk->mServer += stepCount;
     // This may overflow, but client is not supposed to rely on it
-    cblk->u.mStatic.mBufferPosition = (uint32_t) newPosition;
+    StaticAudioTrackPosLoop posLoop;
+    posLoop.mBufferPosition = mState.mPosition;
+    posLoop.mLoopCount = mState.mLoopCount;
+    mPosLoopMutator.push(posLoop);
     if (setFlags != 0) {
         (void) android_atomic_or(setFlags, &cblk->mFlags);
         // this would be a good place to wake a futex
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 6099a05..8e3b633 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -119,7 +119,7 @@
         // haveSharedBuffer
         if (sharedBuffer != 0) {
             data.writeInt32(true);
-            data.writeStrongBinder(sharedBuffer->asBinder());
+            data.writeStrongBinder(IInterface::asBinder(sharedBuffer));
         } else {
             data.writeInt32(false);
         }
@@ -419,7 +419,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeStrongBinder(client->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(client));
         remote()->transact(REGISTER_CLIENT, data, &reply);
     }
 
@@ -716,7 +716,7 @@
 
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.write(pDesc, sizeof(effect_descriptor_t));
-        data.writeStrongBinder(client->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(client));
         data.writeInt32(priority);
         data.writeInt32((int32_t) output);
         data.writeInt32(sessionId);
@@ -939,7 +939,7 @@
             reply->writeInt32(flags);
             reply->writeInt32(sessionId);
             reply->writeInt32(status);
-            reply->writeStrongBinder(track->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(track));
             return NO_ERROR;
         } break;
         case OPEN_RECORD: {
@@ -966,11 +966,9 @@
             reply->writeInt32(sessionId);
             reply->writeInt64(notificationFrames);
             reply->writeInt32(status);
-            reply->writeStrongBinder(record != NULL ? record->asBinder()
-                                                    : NULL);
-            reply->writeStrongBinder(cblk != NULL ? cblk->asBinder() : NULL);
-            reply->writeStrongBinder(buffers != NULL ? buffers->asBinder()
-                                                     : NULL);
+            reply->writeStrongBinder(IInterface::asBinder(record));
+            reply->writeStrongBinder(IInterface::asBinder(cblk));
+            reply->writeStrongBinder(IInterface::asBinder(buffers));
             return NO_ERROR;
         } break;
         case SAMPLE_RATE: {
@@ -1256,7 +1254,7 @@
             reply->writeInt32(status);
             reply->writeInt32(id);
             reply->writeInt32(enabled);
-            reply->writeStrongBinder(effect->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(effect));
             reply->write(&desc, sizeof(effect_descriptor_t));
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 89178f1..f2ff27b 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -41,7 +41,7 @@
     START_OUTPUT,
     STOP_OUTPUT,
     RELEASE_OUTPUT,
-    GET_INPUT,
+    GET_INPUT_FOR_ATTR,
     START_INPUT,
     STOP_INPUT,
     RELEASE_INPUT,
@@ -69,9 +69,12 @@
     GET_OUTPUT_FOR_ATTR,
     ACQUIRE_SOUNDTRIGGER_SESSION,
     RELEASE_SOUNDTRIGGER_SESSION,
-    GET_PHONE_STATE
+    GET_PHONE_STATE,
+    REGISTER_POLICY_MIXES,
 };
 
+#define MAX_ITEMS_PER_LIST 1024
+
 class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
 {
 public:
@@ -83,13 +86,15 @@
     virtual status_t setDeviceConnectionState(
                                     audio_devices_t device,
                                     audio_policy_dev_state_t state,
-                                    const char *device_address)
+                                    const char *device_address,
+                                    const char *device_name)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(static_cast <uint32_t>(device));
         data.writeInt32(static_cast <uint32_t>(state));
         data.writeCString(device_address);
+        data.writeCString(device_name);
         remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply);
         return static_cast <status_t> (reply.readInt32());
     }
@@ -160,21 +165,45 @@
         return static_cast <audio_io_handle_t> (reply.readInt32());
     }
 
-    virtual audio_io_handle_t getOutputForAttr(
-                                            const audio_attributes_t *attr,
-                                            uint32_t samplingRate,
-                                            audio_format_t format,
-                                            audio_channel_mask_t channelMask,
-                                            audio_output_flags_t flags,
-                                            const audio_offload_info_t *offloadInfo)
+    virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+                                        audio_io_handle_t *output,
+                                        audio_session_t session,
+                                        audio_stream_type_t *stream,
+                                        uint32_t samplingRate,
+                                        audio_format_t format,
+                                        audio_channel_mask_t channelMask,
+                                        audio_output_flags_t flags,
+                                        const audio_offload_info_t *offloadInfo)
         {
             Parcel data, reply;
             data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
             if (attr == NULL) {
-                ALOGE("Writing NULL audio attributes - shouldn't happen");
-                return (audio_io_handle_t) 0;
+                if (stream == NULL) {
+                    ALOGE("getOutputForAttr(): NULL audio attributes and stream type");
+                    return BAD_VALUE;
+                }
+                if (*stream == AUDIO_STREAM_DEFAULT) {
+                    ALOGE("getOutputForAttr unspecified stream type");
+                    return BAD_VALUE;
+                }
             }
-            data.write(attr, sizeof(audio_attributes_t));
+            if (output == NULL) {
+                ALOGE("getOutputForAttr NULL output - shouldn't happen");
+                return BAD_VALUE;
+            }
+            if (attr == NULL) {
+                data.writeInt32(0);
+            } else {
+                data.writeInt32(1);
+                data.write(attr, sizeof(audio_attributes_t));
+            }
+            data.writeInt32(session);
+            if (stream == NULL) {
+                data.writeInt32(0);
+            } else {
+                data.writeInt32(1);
+                data.writeInt32(*stream);
+            }
             data.writeInt32(samplingRate);
             data.writeInt32(static_cast <uint32_t>(format));
             data.writeInt32(channelMask);
@@ -186,62 +215,93 @@
                 data.writeInt32(1);
                 data.write(offloadInfo, sizeof(audio_offload_info_t));
             }
-            remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply);
-            return static_cast <audio_io_handle_t> (reply.readInt32());
+            status_t status = remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            status = (status_t)reply.readInt32();
+            if (status != NO_ERROR) {
+                return status;
+            }
+            *output = (audio_io_handle_t)reply.readInt32();
+            if (stream != NULL) {
+                *stream = (audio_stream_type_t)reply.readInt32();
+            }
+            return status;
         }
 
     virtual status_t startOutput(audio_io_handle_t output,
                                  audio_stream_type_t stream,
-                                 int session)
+                                 audio_session_t session)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(output);
         data.writeInt32((int32_t) stream);
-        data.writeInt32(session);
+        data.writeInt32((int32_t)session);
         remote()->transact(START_OUTPUT, data, &reply);
         return static_cast <status_t> (reply.readInt32());
     }
 
     virtual status_t stopOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
-                                int session)
+                                audio_session_t session)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(output);
         data.writeInt32((int32_t) stream);
-        data.writeInt32(session);
+        data.writeInt32((int32_t)session);
         remote()->transact(STOP_OUTPUT, data, &reply);
         return static_cast <status_t> (reply.readInt32());
     }
 
-    virtual void releaseOutput(audio_io_handle_t output)
+    virtual void releaseOutput(audio_io_handle_t output,
+                               audio_stream_type_t stream,
+                               audio_session_t session)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(output);
+        data.writeInt32((int32_t)stream);
+        data.writeInt32((int32_t)session);
         remote()->transact(RELEASE_OUTPUT, data, &reply);
     }
 
-    virtual audio_io_handle_t getInput(
-                                    audio_source_t inputSource,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    int audioSession,
-                                    audio_input_flags_t flags)
+    virtual status_t getInputForAttr(const audio_attributes_t *attr,
+                                     audio_io_handle_t *input,
+                                     audio_session_t session,
+                                     uint32_t samplingRate,
+                                     audio_format_t format,
+                                     audio_channel_mask_t channelMask,
+                                     audio_input_flags_t flags)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
-        data.writeInt32((int32_t) inputSource);
+        if (attr == NULL) {
+            ALOGE("getInputForAttr NULL attr - shouldn't happen");
+            return BAD_VALUE;
+        }
+        if (input == NULL) {
+            ALOGE("getInputForAttr NULL input - shouldn't happen");
+            return BAD_VALUE;
+        }
+        data.write(attr, sizeof(audio_attributes_t));
+        data.writeInt32(session);
         data.writeInt32(samplingRate);
         data.writeInt32(static_cast <uint32_t>(format));
         data.writeInt32(channelMask);
-        data.writeInt32(audioSession);
         data.writeInt32(flags);
-        remote()->transact(GET_INPUT, data, &reply);
-        return static_cast <audio_io_handle_t> (reply.readInt32());
+        status_t status = remote()->transact(GET_INPUT_FOR_ATTR, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = reply.readInt32();
+        if (status != NO_ERROR) {
+            return status;
+        }
+        *input = (audio_io_handle_t)reply.readInt32();
+        return NO_ERROR;
     }
 
     virtual status_t startInput(audio_io_handle_t input,
@@ -572,7 +632,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
-        data.writeStrongBinder(client->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(client));
         remote()->transact(REGISTER_CLIENT, data, &reply);
     }
 
@@ -620,6 +680,38 @@
         }
         return (audio_mode_t)reply.readInt32();
     }
+
+    virtual status_t registerPolicyMixes(Vector<AudioMix> mixes, bool registration)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(registration ? 1 : 0);
+        size_t size = mixes.size();
+        if (size > MAX_MIXES_PER_POLICY) {
+            size = MAX_MIXES_PER_POLICY;
+        }
+        size_t sizePosition = data.dataPosition();
+        data.writeInt32(size);
+        size_t finalSize = size;
+        for (size_t i = 0; i < size; i++) {
+            size_t position = data.dataPosition();
+            if (mixes[i].writeToParcel(&data) != NO_ERROR) {
+                data.setDataPosition(position);
+                finalSize--;
+            }
+        }
+        if (size != finalSize) {
+            size_t position = data.dataPosition();
+            data.setDataPosition(sizePosition);
+            data.writeInt32(finalSize);
+            data.setDataPosition(position);
+        }
+        status_t status = remote()->transact(REGISTER_POLICY_MIXES, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -638,9 +730,11 @@
             audio_policy_dev_state_t state =
                     static_cast <audio_policy_dev_state_t>(data.readInt32());
             const char *device_address = data.readCString();
+            const char *device_name = data.readCString();
             reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
                                                                               state,
-                                                                              device_address)));
+                                                                              device_address,
+                                                                              device_name)));
             return NO_ERROR;
         } break;
 
@@ -706,7 +800,16 @@
         case GET_OUTPUT_FOR_ATTR: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_attributes_t attr;
-            data.read(&attr, sizeof(audio_attributes_t));
+            bool hasAttributes = data.readInt32() != 0;
+            if (hasAttributes) {
+                data.read(&attr, sizeof(audio_attributes_t));
+            }
+            audio_session_t session = (audio_session_t)data.readInt32();
+            audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
+            bool hasStream = data.readInt32() != 0;
+            if (hasStream) {
+                stream = (audio_stream_type_t)data.readInt32();
+            }
             uint32_t samplingRate = data.readInt32();
             audio_format_t format = (audio_format_t) data.readInt32();
             audio_channel_mask_t channelMask = data.readInt32();
@@ -717,13 +820,14 @@
             if (hasOffloadInfo) {
                 data.read(&offloadInfo, sizeof(audio_offload_info_t));
             }
-            audio_io_handle_t output = getOutputForAttr(&attr,
-                    samplingRate,
-                    format,
-                    channelMask,
-                    flags,
-                    hasOffloadInfo ? &offloadInfo : NULL);
-            reply->writeInt32(static_cast <int>(output));
+            audio_io_handle_t output;
+            status_t status = getOutputForAttr(hasAttributes ? &attr : NULL,
+                    &output, session, &stream,
+                    samplingRate, format, channelMask,
+                    flags, hasOffloadInfo ? &offloadInfo : NULL);
+            reply->writeInt32(status);
+            reply->writeInt32(output);
+            reply->writeInt32(stream);
             return NO_ERROR;
         } break;
 
@@ -732,7 +836,7 @@
             audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
             audio_stream_type_t stream =
                                 static_cast <audio_stream_type_t>(data.readInt32());
-            int session = data.readInt32();
+            audio_session_t session = (audio_session_t)data.readInt32();
             reply->writeInt32(static_cast <uint32_t>(startOutput(output,
                                                                  stream,
                                                                  session)));
@@ -744,7 +848,7 @@
             audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
             audio_stream_type_t stream =
                                 static_cast <audio_stream_type_t>(data.readInt32());
-            int session = data.readInt32();
+            audio_session_t session = (audio_session_t)data.readInt32();
             reply->writeInt32(static_cast <uint32_t>(stopOutput(output,
                                                                 stream,
                                                                 session)));
@@ -754,25 +858,29 @@
         case RELEASE_OUTPUT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
-            releaseOutput(output);
+            audio_stream_type_t stream = (audio_stream_type_t)data.readInt32();
+            audio_session_t session = (audio_session_t)data.readInt32();
+            releaseOutput(output, stream, session);
             return NO_ERROR;
         } break;
 
-        case GET_INPUT: {
+        case GET_INPUT_FOR_ATTR: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            audio_source_t inputSource = (audio_source_t) data.readInt32();
+            audio_attributes_t attr;
+            data.read(&attr, sizeof(audio_attributes_t));
+            audio_session_t session = (audio_session_t)data.readInt32();
             uint32_t samplingRate = data.readInt32();
             audio_format_t format = (audio_format_t) data.readInt32();
             audio_channel_mask_t channelMask = data.readInt32();
-            int audioSession = data.readInt32();
             audio_input_flags_t flags = (audio_input_flags_t) data.readInt32();
-            audio_io_handle_t input = getInput(inputSource,
-                                               samplingRate,
-                                               format,
-                                               channelMask,
-                                               audioSession,
-                                               flags);
-            reply->writeInt32(static_cast <int>(input));
+            audio_io_handle_t input;
+            status_t status = getInputForAttr(&attr, &input, session,
+                                              samplingRate, format, channelMask,
+                                              flags);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32(input);
+            }
             return NO_ERROR;
         } break;
 
@@ -952,10 +1060,18 @@
             audio_port_role_t role = (audio_port_role_t)data.readInt32();
             audio_port_type_t type = (audio_port_type_t)data.readInt32();
             unsigned int numPortsReq = data.readInt32();
+            if (numPortsReq > MAX_ITEMS_PER_LIST) {
+                numPortsReq = MAX_ITEMS_PER_LIST;
+            }
             unsigned int numPorts = numPortsReq;
-            unsigned int generation;
             struct audio_port *ports =
                     (struct audio_port *)calloc(numPortsReq, sizeof(struct audio_port));
+            if (ports == NULL) {
+                reply->writeInt32(NO_MEMORY);
+                reply->writeInt32(0);
+                return NO_ERROR;
+            }
+            unsigned int generation;
             status_t status = listAudioPorts(role, type, &numPorts, ports, &generation);
             reply->writeInt32(status);
             reply->writeInt32(numPorts);
@@ -1009,11 +1125,19 @@
         case LIST_AUDIO_PATCHES: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             unsigned int numPatchesReq = data.readInt32();
+            if (numPatchesReq > MAX_ITEMS_PER_LIST) {
+                numPatchesReq = MAX_ITEMS_PER_LIST;
+            }
             unsigned int numPatches = numPatchesReq;
-            unsigned int generation;
             struct audio_patch *patches =
                     (struct audio_patch *)calloc(numPatchesReq,
                                                  sizeof(struct audio_patch));
+            if (patches == NULL) {
+                reply->writeInt32(NO_MEMORY);
+                reply->writeInt32(0);
+                return NO_ERROR;
+            }
+            unsigned int generation;
             status_t status = listAudioPatches(&numPatches, patches, &generation);
             reply->writeInt32(status);
             reply->writeInt32(numPatches);
@@ -1078,6 +1202,25 @@
             return NO_ERROR;
         } break;
 
+        case REGISTER_POLICY_MIXES: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            bool registration = data.readInt32() == 1;
+            Vector<AudioMix> mixes;
+            size_t size = (size_t)data.readInt32();
+            if (size > MAX_MIXES_PER_POLICY) {
+                size = MAX_MIXES_PER_POLICY;
+            }
+            for (size_t i = 0; i < size; i++) {
+                AudioMix mix;
+                if (mix.readFromParcel((Parcel*)&data) == NO_ERROR) {
+                    mixes.add(mix);
+                }
+            }
+            status_t status = registerPolicyMixes(mixes, registration);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        } break;
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index 265bb1b..df209fd 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -137,7 +137,7 @@
                                       int64_t pts) {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
-        data.writeStrongBinder(buffer->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(buffer));
         data.writeInt64(pts);
         status_t status = remote()->transact(QUEUE_TIMED_BUFFER,
                                              data, &reply);
@@ -207,7 +207,7 @@
     switch (code) {
         case GET_CBLK: {
             CHECK_INTERFACE(IAudioTrack, data, reply);
-            reply->writeStrongBinder(getCblk()->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(getCblk()));
             return NO_ERROR;
         } break;
         case START: {
@@ -241,7 +241,7 @@
             status_t status = allocateTimedBuffer(data.readInt64(), &buffer);
             reply->writeInt32(status);
             if (status == NO_ERROR) {
-                reply->writeStrongBinder(buffer->asBinder());
+                reply->writeStrongBinder(IInterface::asBinder(buffer));
             }
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp
index 7e74de9..b08fa82 100644
--- a/media/libmedia/IDrm.cpp
+++ b/media/libmedia/IDrm.cpp
@@ -450,7 +450,7 @@
     virtual status_t setListener(const sp<IDrmClient>& listener) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-        data.writeStrongBinder(listener->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(listener));
         remote()->transact(SET_LISTENER, data, &reply);
         return reply.readInt32();
     }
diff --git a/media/libmedia/IEffect.cpp b/media/libmedia/IEffect.cpp
index b94012a..c2fff78 100644
--- a/media/libmedia/IEffect.cpp
+++ b/media/libmedia/IEffect.cpp
@@ -190,7 +190,7 @@
 
         case GET_CBLK: {
             CHECK_INTERFACE(IEffect, data, reply);
-            reply->writeStrongBinder(getCblk()->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(getCblk()));
             return NO_ERROR;
         } break;
 
diff --git a/media/libmedia/IHDCP.cpp b/media/libmedia/IHDCP.cpp
index 1cf987a..9122f75 100644
--- a/media/libmedia/IHDCP.cpp
+++ b/media/libmedia/IHDCP.cpp
@@ -65,7 +65,7 @@
     virtual status_t setObserver(const sp<IHDCPObserver> &observer) {
         Parcel data, reply;
         data.writeInterfaceToken(IHDCP::getInterfaceDescriptor());
-        data.writeStrongBinder(observer->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(observer));
         remote()->transact(HDCP_SET_OBSERVER, data, &reply);
         return reply.readInt32();
     }
diff --git a/media/libmedia/IMediaDeathNotifier.cpp b/media/libmedia/IMediaDeathNotifier.cpp
index 10b4934..38e9ca0 100644
--- a/media/libmedia/IMediaDeathNotifier.cpp
+++ b/media/libmedia/IMediaDeathNotifier.cpp
@@ -104,7 +104,7 @@
     Mutex::Autolock _l(sServiceLock);
     sObitRecipients.clear();
     if (sMediaPlayerService != 0) {
-        sMediaPlayerService->asBinder()->unlinkToDeath(this);
+        IInterface::asBinder(sMediaPlayerService)->unlinkToDeath(this);
     }
 }
 
diff --git a/media/libmedia/IMediaLogService.cpp b/media/libmedia/IMediaLogService.cpp
index 8a66c7c..a4af7b7 100644
--- a/media/libmedia/IMediaLogService.cpp
+++ b/media/libmedia/IMediaLogService.cpp
@@ -42,7 +42,7 @@
     virtual void    registerWriter(const sp<IMemory>& shared, size_t size, const char *name) {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaLogService::getInterfaceDescriptor());
-        data.writeStrongBinder(shared->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(shared));
         data.writeInt64((int64_t) size);
         data.writeCString(name);
         status_t status = remote()->transact(REGISTER_WRITER, data, &reply);
@@ -52,7 +52,7 @@
     virtual void    unregisterWriter(const sp<IMemory>& shared) {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaLogService::getInterfaceDescriptor());
-        data.writeStrongBinder(shared->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(shared));
         status_t status = remote()->transact(UNREGISTER_WRITER, data, &reply);
         // FIXME ignores status
     }
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 38f717c..aa2665a 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -95,7 +95,7 @@
         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
         data.writeInt32(httpService != NULL);
         if (httpService != NULL) {
-            data.writeStrongBinder(httpService->asBinder());
+            data.writeStrongBinder(IInterface::asBinder(httpService));
         }
         data.writeCString(srcUrl);
 
@@ -246,7 +246,7 @@
             sp<IMemory> bitmap = getFrameAtTime(timeUs, option);
             if (bitmap != 0) {  // Don't send NULL across the binder interface
                 reply->writeInt32(NO_ERROR);
-                reply->writeStrongBinder(bitmap->asBinder());
+                reply->writeStrongBinder(IInterface::asBinder(bitmap));
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
@@ -263,7 +263,7 @@
             sp<IMemory> albumArt = extractAlbumArt();
             if (albumArt != 0) {  // Don't send NULL across the binder interface
                 reply->writeInt32(NO_ERROR);
-                reply->writeStrongBinder(albumArt->asBinder());
+                reply->writeStrongBinder(IInterface::asBinder(albumArt));
             } else {
                 reply->writeInt32(UNKNOWN_ERROR);
             }
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index d778d05..dcd5670 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -39,6 +39,7 @@
     START,
     STOP,
     IS_PLAYING,
+    SET_PLAYBACK_RATE,
     PAUSE,
     SEEK_TO,
     GET_CURRENT_POSITION,
@@ -85,7 +86,7 @@
         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
         data.writeInt32(httpService != NULL);
         if (httpService != NULL) {
-            data.writeStrongBinder(httpService->asBinder());
+            data.writeStrongBinder(IInterface::asBinder(httpService));
         }
         data.writeCString(url);
         if (headers == NULL) {
@@ -115,7 +116,7 @@
     status_t setDataSource(const sp<IStreamSource> &source) {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
-        data.writeStrongBinder(source->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(source));
         remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply);
         return reply.readInt32();
     }
@@ -125,7 +126,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
-        sp<IBinder> b(bufferProducer->asBinder());
+        sp<IBinder> b(IInterface::asBinder(bufferProducer));
         data.writeStrongBinder(b);
         remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply);
         return reply.readInt32();
@@ -164,6 +165,15 @@
         return reply.readInt32();
     }
 
+    status_t setPlaybackRate(float rate)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeFloat(rate);
+        remote()->transact(SET_PLAYBACK_RATE, data, &reply);
+        return reply.readInt32();
+    }
+
     status_t pause()
     {
         Parcel data, reply;
@@ -323,7 +333,7 @@
     status_t setNextPlayer(const sp<IMediaPlayer>& player) {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
-        sp<IBinder> b(player->asBinder());
+        sp<IBinder> b(IInterface::asBinder(player));
         data.writeStrongBinder(b);
         remote()->transact(SET_NEXT_PLAYER, data, &reply);
         return reply.readInt32();
@@ -426,6 +436,11 @@
             reply->writeInt32(ret);
             return NO_ERROR;
         } break;
+        case SET_PLAYBACK_RATE: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(setPlaybackRate(data.readFloat()));
+            return NO_ERROR;
+        } break;
         case PAUSE: {
             CHECK_INTERFACE(IMediaPlayer, data, reply);
             reply->writeInt32(pause());
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 2e02d17..feea267 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -39,8 +39,6 @@
 
 enum {
     CREATE = IBinder::FIRST_CALL_TRANSACTION,
-    DECODE_URL,
-    DECODE_FD,
     CREATE_MEDIA_RECORDER,
     CREATE_METADATA_RETRIEVER,
     GET_OMX,
@@ -73,7 +71,7 @@
             const sp<IMediaPlayerClient>& client, int audioSessionId) {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        data.writeStrongBinder(client->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(client));
         data.writeInt32(audioSessionId);
 
         remote()->transact(CREATE, data, &reply);
@@ -88,59 +86,6 @@
         return interface_cast<IMediaRecorder>(reply.readStrongBinder());
     }
 
-    virtual status_t decode(
-            const sp<IMediaHTTPService> &httpService,
-            const char* url,
-            uint32_t *pSampleRate,
-            int* pNumChannels,
-            audio_format_t* pFormat,
-            const sp<IMemoryHeap>& heap,
-            size_t *pSize)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        data.writeInt32(httpService != NULL);
-        if (httpService != NULL) {
-            data.writeStrongBinder(httpService->asBinder());
-        }
-        data.writeCString(url);
-        data.writeStrongBinder(heap->asBinder());
-        status_t status = remote()->transact(DECODE_URL, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-            if (status == NO_ERROR) {
-                *pSampleRate = uint32_t(reply.readInt32());
-                *pNumChannels = reply.readInt32();
-                *pFormat = (audio_format_t)reply.readInt32();
-                *pSize = (size_t)reply.readInt32();
-            }
-        }
-        return status;
-    }
-
-    virtual status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
-                               int* pNumChannels, audio_format_t* pFormat,
-                               const sp<IMemoryHeap>& heap, size_t *pSize)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        data.writeFileDescriptor(fd);
-        data.writeInt64(offset);
-        data.writeInt64(length);
-        data.writeStrongBinder(heap->asBinder());
-        status_t status = remote()->transact(DECODE_FD, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-            if (status == NO_ERROR) {
-                *pSampleRate = uint32_t(reply.readInt32());
-                *pNumChannels = reply.readInt32();
-                *pFormat = (audio_format_t)reply.readInt32();
-                *pSize = (size_t)reply.readInt32();
-            }
-        }
-        return status;
-    }
-
     virtual sp<IOMX> getOMX() {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -188,7 +133,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        data.writeStrongBinder(client->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(client));
         data.writeString8(iface);
         remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply);
         return interface_cast<IRemoteDisplay>(reply.readStrongBinder());
@@ -216,95 +161,44 @@
                 interface_cast<IMediaPlayerClient>(data.readStrongBinder());
             int audioSessionId = data.readInt32();
             sp<IMediaPlayer> player = create(client, audioSessionId);
-            reply->writeStrongBinder(player->asBinder());
-            return NO_ERROR;
-        } break;
-        case DECODE_URL: {
-            CHECK_INTERFACE(IMediaPlayerService, data, reply);
-            sp<IMediaHTTPService> httpService;
-            if (data.readInt32()) {
-                httpService =
-                    interface_cast<IMediaHTTPService>(data.readStrongBinder());
-            }
-            const char* url = data.readCString();
-            sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
-            uint32_t sampleRate;
-            int numChannels;
-            audio_format_t format;
-            size_t size;
-            status_t status =
-                decode(httpService,
-                       url,
-                       &sampleRate,
-                       &numChannels,
-                       &format,
-                       heap,
-                       &size);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->writeInt32(sampleRate);
-                reply->writeInt32(numChannels);
-                reply->writeInt32((int32_t)format);
-                reply->writeInt32((int32_t)size);
-            }
-            return NO_ERROR;
-        } break;
-        case DECODE_FD: {
-            CHECK_INTERFACE(IMediaPlayerService, data, reply);
-            int fd = dup(data.readFileDescriptor());
-            int64_t offset = data.readInt64();
-            int64_t length = data.readInt64();
-            sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
-            uint32_t sampleRate;
-            int numChannels;
-            audio_format_t format;
-            size_t size;
-            status_t status = decode(fd, offset, length, &sampleRate, &numChannels, &format,
-                                     heap, &size);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->writeInt32(sampleRate);
-                reply->writeInt32(numChannels);
-                reply->writeInt32((int32_t)format);
-                reply->writeInt32((int32_t)size);
-            }
+            reply->writeStrongBinder(IInterface::asBinder(player));
             return NO_ERROR;
         } break;
         case CREATE_MEDIA_RECORDER: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             sp<IMediaRecorder> recorder = createMediaRecorder();
-            reply->writeStrongBinder(recorder->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(recorder));
             return NO_ERROR;
         } break;
         case CREATE_METADATA_RETRIEVER: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             sp<IMediaMetadataRetriever> retriever = createMetadataRetriever();
-            reply->writeStrongBinder(retriever->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(retriever));
             return NO_ERROR;
         } break;
         case GET_OMX: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             sp<IOMX> omx = getOMX();
-            reply->writeStrongBinder(omx->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(omx));
             return NO_ERROR;
         } break;
         case MAKE_CRYPTO: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             sp<ICrypto> crypto = makeCrypto();
-            reply->writeStrongBinder(crypto->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(crypto));
             return NO_ERROR;
         } break;
         case MAKE_DRM: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             sp<IDrm> drm = makeDrm();
-            reply->writeStrongBinder(drm->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(drm));
             return NO_ERROR;
         } break;
         case MAKE_HDCP: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             bool createEncryptionModule = data.readInt32();
             sp<IHDCP> hdcp = makeHDCP(createEncryptionModule);
-            reply->writeStrongBinder(hdcp->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(hdcp));
             return NO_ERROR;
         } break;
         case ADD_BATTERY_DATA: {
@@ -324,13 +218,13 @@
                     interface_cast<IRemoteDisplayClient>(data.readStrongBinder()));
             String8 iface(data.readString8());
             sp<IRemoteDisplay> display(listenForRemoteDisplay(client, iface));
-            reply->writeStrongBinder(display->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(display));
             return NO_ERROR;
         } break;
         case GET_CODEC_LIST: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             sp<IMediaCodecList> mcl = getCodecList();
-            reply->writeStrongBinder(mcl->asBinder());
+            reply->writeStrongBinder(IInterface::asBinder(mcl));
             return NO_ERROR;
         } break;
         default:
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 95af006..9181f86 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -46,7 +46,6 @@
     SET_OUTPUT_FORMAT,
     SET_VIDEO_ENCODER,
     SET_AUDIO_ENCODER,
-    SET_OUTPUT_FILE_PATH,
     SET_OUTPUT_FILE_FD,
     SET_VIDEO_SIZE,
     SET_VIDEO_FRAMERATE,
@@ -70,8 +69,8 @@
         ALOGV("setCamera(%p,%p)", camera.get(), proxy.get());
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
-        data.writeStrongBinder(camera->asBinder());
-        data.writeStrongBinder(proxy->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(camera));
+        data.writeStrongBinder(IInterface::asBinder(proxy));
         remote()->transact(SET_CAMERA, data, &reply);
         return reply.readInt32();
     }
@@ -94,7 +93,7 @@
         ALOGV("setPreviewSurface(%p)", surface.get());
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
-        data.writeStrongBinder(surface->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(surface));
         remote()->transact(SET_PREVIEW_SURFACE, data, &reply);
         return reply.readInt32();
     }
@@ -158,16 +157,6 @@
         return reply.readInt32();
     }
 
-    status_t setOutputFile(const char* path)
-    {
-        ALOGV("setOutputFile(%s)", path);
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
-        data.writeCString(path);
-        remote()->transact(SET_OUTPUT_FILE_PATH, data, &reply);
-        return reply.readInt32();
-    }
-
     status_t setOutputFile(int fd, int64_t offset, int64_t length) {
         ALOGV("setOutputFile(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
         Parcel data, reply;
@@ -215,7 +204,7 @@
         ALOGV("setListener(%p)", listener.get());
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
-        data.writeStrongBinder(listener->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(listener));
         remote()->transact(SET_LISTENER, data, &reply);
         return reply.readInt32();
     }
@@ -300,7 +289,8 @@
 // ----------------------------------------------------------------------
 
 status_t BnMediaRecorder::onTransact(
-                                     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+                                     uint32_t code, const Parcel& data, Parcel* reply,
+                                     uint32_t flags)
 {
     switch (code) {
         case RELEASE: {
@@ -390,13 +380,6 @@
             return NO_ERROR;
 
         } break;
-        case SET_OUTPUT_FILE_PATH: {
-            ALOGV("SET_OUTPUT_FILE_PATH");
-            CHECK_INTERFACE(IMediaRecorder, data, reply);
-            const char* path = data.readCString();
-            reply->writeInt32(setOutputFile(path));
-            return NO_ERROR;
-        } break;
         case SET_OUTPUT_FILE_FD: {
             ALOGV("SET_OUTPUT_FILE_FD");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
@@ -445,7 +428,8 @@
         case SET_PREVIEW_SURFACE: {
             ALOGV("SET_PREVIEW_SURFACE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
-            sp<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
+            sp<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(
+                    data.readStrongBinder());
             reply->writeInt32(setPreviewSurface(surface));
             return NO_ERROR;
         } break;
@@ -468,7 +452,7 @@
             int returnedNull= (surfaceMediaSource == NULL) ? 1 : 0 ;
             reply->writeInt32(returnedNull);
             if (!returnedNull) {
-                reply->writeStrongBinder(surfaceMediaSource->asBinder());
+                reply->writeStrongBinder(IInterface::asBinder(surfaceMediaSource));
             }
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index c583d32..e208df9 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -100,7 +100,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeCString(name);
-        data.writeStrongBinder(observer->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(observer));
         remote()->transact(ALLOCATE_NODE, data, &reply);
 
         status_t err = reply.readInt32();
@@ -248,7 +248,7 @@
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeInt32((int32_t)node);
         data.writeInt32(port_index);
-        data.writeStrongBinder(params->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(params));
         remote()->transact(USE_BUFFER, data, &reply);
 
         status_t err = reply.readInt32();
@@ -418,7 +418,7 @@
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeInt32((int32_t)node);
         data.writeInt32(port_index);
-        data.writeStrongBinder(params->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(params));
         remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
 
         status_t err = reply.readInt32();
@@ -775,7 +775,7 @@
             reply->writeInt32(err);
 
             if (err == OK) {
-                reply->writeStrongBinder(bufferProducer->asBinder());
+                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
             }
 
             return NO_ERROR;
diff --git a/media/libmedia/IRemoteDisplayClient.cpp b/media/libmedia/IRemoteDisplayClient.cpp
index 7190879..9d63bc9 100644
--- a/media/libmedia/IRemoteDisplayClient.cpp
+++ b/media/libmedia/IRemoteDisplayClient.cpp
@@ -42,7 +42,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(IRemoteDisplayClient::getInterfaceDescriptor());
-        data.writeStrongBinder(bufferProducer->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(bufferProducer));
         data.writeInt32(width);
         data.writeInt32(height);
         data.writeInt32(flags);
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
index fe2cc61..d480aef 100644
--- a/media/libmedia/IStreamSource.cpp
+++ b/media/libmedia/IStreamSource.cpp
@@ -55,7 +55,7 @@
     virtual void setListener(const sp<IStreamListener> &listener) {
         Parcel data, reply;
         data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor());
-        data.writeStrongBinder(listener->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(listener));
         remote()->transact(SET_LISTENER, data, &reply);
     }
 
@@ -64,7 +64,7 @@
         data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor());
         data.writeInt64(static_cast<int64_t>(buffers.size()));
         for (size_t i = 0; i < buffers.size(); ++i) {
-            data.writeStrongBinder(buffers.itemAt(i)->asBinder());
+            data.writeStrongBinder(IInterface::asBinder(buffers.itemAt(i)));
         }
         remote()->transact(SET_BUFFERS, data, &reply);
     }
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index f0f1832..271be0c 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -36,7 +36,6 @@
         mPaused(false),
         mMaxTracks(maxTracks),
         mEasData(NULL),
-        mEasJetFileLoc(NULL),
         mTrackBufferSize(trackBufferSize)
 {
     ALOGV("JetPlayer constructor");
@@ -133,10 +132,7 @@
         JET_Shutdown(mEasData);
         EAS_Shutdown(mEasData);
     }
-    if (mEasJetFileLoc) {
-        free(mEasJetFileLoc);
-        mEasJetFileLoc = NULL;
-    }
+    mIoWrapper.clear();
     if (mAudioTrack != 0) {
         mAudioTrack->stop();
         mAudioTrack->flush();
@@ -327,16 +323,9 @@
 
     Mutex::Autolock lock(mMutex);
 
-    mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE));
-    strncpy(mJetFilePath, path, sizeof(mJetFilePath));
-    mJetFilePath[sizeof(mJetFilePath) - 1] = '\0';
-    mEasJetFileLoc->path = mJetFilePath;
+    mIoWrapper = new MidiIoWrapper(path);
 
-    mEasJetFileLoc->fd = 0;
-    mEasJetFileLoc->length = 0;
-    mEasJetFileLoc->offset = 0;
-
-    EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc);
+    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
     if (result != EAS_SUCCESS)
         mState = EAS_STATE_ERROR;
     else
@@ -352,13 +341,9 @@
 
     Mutex::Autolock lock(mMutex);
 
-    mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE));
-    mEasJetFileLoc->fd = fd;
-    mEasJetFileLoc->offset = offset;
-    mEasJetFileLoc->length = length;
-    mEasJetFileLoc->path = NULL;
+    mIoWrapper = new MidiIoWrapper(fd, offset, length);
 
-    EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc);
+    EAS_RESULT result = JET_OpenFile(mEasData, mIoWrapper->getLocator());
     if (result != EAS_SUCCESS)
         mState = EAS_STATE_ERROR;
     else
@@ -423,7 +408,8 @@
     ALOGV("JetPlayer::queueSegment segmentNum=%d, libNum=%d, repeatCount=%d, transpose=%d",
         segmentNum, libNum, repeatCount, transpose);
     Mutex::Autolock lock(mMutex);
-    return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags, userID);
+    return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags,
+            userID);
 }
 
 //-------------------------------------------------------------------------------------------------
@@ -459,13 +445,13 @@
 //-------------------------------------------------------------------------------------------------
 void JetPlayer::dump()
 {
-    ALOGE("JetPlayer dump: JET file=%s", mEasJetFileLoc->path);
 }
 
 void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus)
 {
     if (pJetStatus!=NULL)
-        ALOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d paused=%d",
+        ALOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d "
+                "paused=%d",
                 pJetStatus->currentUserID, pJetStatus->segmentRepeatCount,
                 pJetStatus->numQueuedSegments, pJetStatus->paused);
     else
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index e2e6042..47f9258 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -163,7 +163,8 @@
 }
 
 /*static*/ int
-MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings, const char *name)
+MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings,
+        const char *name)
 {
     int tag = -1;
     for (size_t i = 0; i < nMappings; ++i) {
@@ -295,9 +296,8 @@
     CHECK(codec != -1);
 
     MediaProfiles::AudioEncoderCap *cap =
-        new MediaProfiles::AudioEncoderCap(static_cast<audio_encoder>(codec), atoi(atts[5]), atoi(atts[7]),
-            atoi(atts[9]), atoi(atts[11]), atoi(atts[13]),
-            atoi(atts[15]));
+        new MediaProfiles::AudioEncoderCap(static_cast<audio_encoder>(codec), atoi(atts[5]),
+            atoi(atts[7]), atoi(atts[9]), atoi(atts[11]), atoi(atts[13]), atoi(atts[15]));
     logAudioEncoderCap(*cap);
     return cap;
 }
@@ -330,7 +330,8 @@
           !strcmp("fileFormat", atts[2]) &&
           !strcmp("duration",   atts[4]));
 
-    const size_t nProfileMappings = sizeof(sCamcorderQualityNameMap)/sizeof(sCamcorderQualityNameMap[0]);
+    const size_t nProfileMappings = sizeof(sCamcorderQualityNameMap)/
+            sizeof(sCamcorderQualityNameMap[0]);
     const int quality = findTagForName(sCamcorderQualityNameMap, nProfileMappings, atts[1]);
     CHECK(quality != -1);
 
@@ -722,16 +723,20 @@
 MediaProfiles::createDefaultCamcorderTimeLapseLowProfiles(
         MediaProfiles::CamcorderProfile **lowTimeLapseProfile,
         MediaProfiles::CamcorderProfile **lowSpecificTimeLapseProfile) {
-    *lowTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile(CAMCORDER_QUALITY_TIME_LAPSE_LOW);
-    *lowSpecificTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile(CAMCORDER_QUALITY_TIME_LAPSE_QCIF);
+    *lowTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile(
+            CAMCORDER_QUALITY_TIME_LAPSE_LOW);
+    *lowSpecificTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile(
+            CAMCORDER_QUALITY_TIME_LAPSE_QCIF);
 }
 
 /*static*/ void
 MediaProfiles::createDefaultCamcorderTimeLapseHighProfiles(
         MediaProfiles::CamcorderProfile **highTimeLapseProfile,
         MediaProfiles::CamcorderProfile **highSpecificTimeLapseProfile) {
-    *highTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile(CAMCORDER_QUALITY_TIME_LAPSE_HIGH);
-    *highSpecificTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile(CAMCORDER_QUALITY_TIME_LAPSE_480P);
+    *highTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile(
+            CAMCORDER_QUALITY_TIME_LAPSE_HIGH);
+    *highSpecificTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile(
+            CAMCORDER_QUALITY_TIME_LAPSE_480P);
 }
 
 /*static*/ MediaProfiles::CamcorderProfile*
@@ -809,7 +814,8 @@
 
     // high camcorder time lapse profiles.
     MediaProfiles::CamcorderProfile *highTimeLapseProfile, *highSpecificTimeLapseProfile;
-    createDefaultCamcorderTimeLapseHighProfiles(&highTimeLapseProfile, &highSpecificTimeLapseProfile);
+    createDefaultCamcorderTimeLapseHighProfiles(&highTimeLapseProfile,
+            &highSpecificTimeLapseProfile);
     profiles->mCamcorderProfiles.add(highTimeLapseProfile);
     profiles->mCamcorderProfiles.add(highSpecificTimeLapseProfile);
 
diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp
index 66f7161..d31f721 100644
--- a/media/libmedia/MemoryLeakTrackUtil.cpp
+++ b/media/libmedia/MemoryLeakTrackUtil.cpp
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <unistd.h>
 
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
new file mode 100644
index 0000000..5197ce2
--- /dev/null
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2014 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 "MidiIoWrapper"
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "media/MidiIoWrapper.h"
+
+static int readAt(void *handle, void *buffer, int pos, int size) {
+    return ((android::MidiIoWrapper*)handle)->readAt(buffer, pos, size);
+}
+static int size(void *handle) {
+    return ((android::MidiIoWrapper*)handle)->size();
+}
+
+namespace android {
+
+MidiIoWrapper::MidiIoWrapper(const char *path) {
+    ALOGV("MidiIoWrapper(%s)", path);
+    mFd = open(path, O_RDONLY | O_LARGEFILE);
+    mBase = 0;
+    mLength = lseek(mFd, 0, SEEK_END);
+}
+
+MidiIoWrapper::MidiIoWrapper(int fd, off64_t offset, int64_t size) {
+    ALOGV("MidiIoWrapper(fd=%d)", fd);
+    mFd = dup(fd);
+    mBase = offset;
+    mLength = size;
+}
+
+MidiIoWrapper::MidiIoWrapper(const sp<DataSource> &source) {
+    ALOGV("MidiIoWrapper(DataSource)");
+    mFd = -1;
+    mDataSource = source;
+    off64_t l;
+    if (mDataSource->getSize(&l) == OK) {
+        mLength = l;
+    } else {
+        mLength = 0;
+    }
+}
+
+MidiIoWrapper::~MidiIoWrapper() {
+    ALOGV("~MidiIoWrapper");
+    close(mFd);
+}
+
+int MidiIoWrapper::readAt(void *buffer, int offset, int size) {
+    ALOGV("readAt(%p, %d, %d)", buffer, offset, size);
+
+    if (mDataSource != NULL) {
+        return mDataSource->readAt(offset, buffer, size);
+    }
+    lseek(mFd, mBase + offset, SEEK_SET);
+    if (offset + size > mLength) {
+        size = mLength - offset;
+    }
+    return read(mFd, buffer, size);
+}
+
+int MidiIoWrapper::size() {
+    ALOGV("size() = %d", int(mLength));
+    return mLength;
+}
+
+EAS_FILE_LOCATOR MidiIoWrapper::getLocator() {
+    mEasFile.handle = this;
+    mEasFile.readAt = ::readAt;
+    mEasFile.size = ::size;
+    return &mEasFile;
+}
+
+}  // namespace android
diff --git a/media/libmedia/SingleStateQueue.cpp b/media/libmedia/SingleStateQueue.cpp
deleted file mode 100644
index 3503baa..0000000
--- a/media/libmedia/SingleStateQueue.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2012 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 <new>
-#include <cutils/atomic.h>
-#include <cutils/atomic-inline.h> // for android_memory_barrier()
-#include <media/SingleStateQueue.h>
-
-namespace android {
-
-template<typename T> SingleStateQueue<T>::Mutator::Mutator(Shared *shared)
-    : mSequence(0), mShared((Shared *) shared)
-{
-    // exactly one of Mutator and Observer must initialize, currently it is Observer
-    //shared->init();
-}
-
-template<typename T> int32_t SingleStateQueue<T>::Mutator::push(const T& value)
-{
-    Shared *shared = mShared;
-    int32_t sequence = mSequence;
-    sequence++;
-    android_atomic_acquire_store(sequence, &shared->mSequence);
-    shared->mValue = value;
-    sequence++;
-    android_atomic_release_store(sequence, &shared->mSequence);
-    mSequence = sequence;
-    // consider signalling a futex here, if we know that observer is waiting
-    return sequence;
-}
-
-template<typename T> bool SingleStateQueue<T>::Mutator::ack()
-{
-    return mShared->mAck - mSequence == 0;
-}
-
-template<typename T> bool SingleStateQueue<T>::Mutator::ack(int32_t sequence)
-{
-    // this relies on 2's complement rollover to detect an ancient sequence number
-    return mShared->mAck - sequence >= 0;
-}
-
-template<typename T> SingleStateQueue<T>::Observer::Observer(Shared *shared)
-    : mSequence(0), mSeed(1), mShared((Shared *) shared)
-{
-    // exactly one of Mutator and Observer must initialize, currently it is Observer
-    shared->init();
-}
-
-template<typename T> bool SingleStateQueue<T>::Observer::poll(T& value)
-{
-    Shared *shared = mShared;
-    int32_t before = shared->mSequence;
-    if (before == mSequence) {
-        return false;
-    }
-    for (int tries = 0; ; ) {
-        const int MAX_TRIES = 5;
-        if (before & 1) {
-            if (++tries >= MAX_TRIES) {
-                return false;
-            }
-            before = shared->mSequence;
-        } else {
-            android_memory_barrier();
-            T temp = shared->mValue;
-            int32_t after = android_atomic_release_load(&shared->mSequence);
-            if (after == before) {
-                value = temp;
-                shared->mAck = before;
-                mSequence = before;
-                return true;
-            }
-            if (++tries >= MAX_TRIES) {
-                return false;
-            }
-            before = after;
-        }
-    }
-}
-
-#if 0
-template<typename T> SingleStateQueue<T>::SingleStateQueue(void /*Shared*/ *shared)
-{
-    ((Shared *) shared)->init();
-}
-#endif
-
-}   // namespace android
-
-// hack for gcc
-#ifdef SINGLE_STATE_QUEUE_INSTANTIATIONS
-#include SINGLE_STATE_QUEUE_INSTANTIATIONS
-#endif
diff --git a/media/libmedia/SingleStateQueueInstantiations.cpp b/media/libmedia/SingleStateQueueInstantiations.cpp
deleted file mode 100644
index 0265c8c..0000000
--- a/media/libmedia/SingleStateQueueInstantiations.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2012 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 <media/SingleStateQueue.h>
-#include <private/media/StaticAudioTrackState.h>
-#include <media/AudioTimestamp.h>
-
-// FIXME hack for gcc
-
-namespace android {
-
-template class SingleStateQueue<StaticAudioTrackState>; // typedef StaticAudioTrackSingleStateQueue
-template class SingleStateQueue<AudioTimestamp>;        // typedef AudioTimestampSingleStateQueue
-
-}
diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp
deleted file mode 100644
index d2e381b..0000000
--- a/media/libmedia/SoundPool.cpp
+++ /dev/null
@@ -1,921 +0,0 @@
-/*
- * Copyright (C) 2007 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 "SoundPool"
-
-#include <inttypes.h>
-
-#include <utils/Log.h>
-
-#define USE_SHARED_MEM_BUFFER
-
-#include <media/AudioTrack.h>
-#include <media/IMediaHTTPService.h>
-#include <media/mediaplayer.h>
-#include <media/SoundPool.h>
-#include "SoundPoolThread.h"
-#include <media/AudioPolicyHelper.h>
-
-namespace android
-{
-
-int kDefaultBufferCount = 4;
-uint32_t kMaxSampleRate = 48000;
-uint32_t kDefaultSampleRate = 44100;
-uint32_t kDefaultFrameCount = 1200;
-size_t kDefaultHeapSize = 1024 * 1024; // 1MB
-
-
-SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes)
-{
-    ALOGV("SoundPool constructor: maxChannels=%d, attr.usage=%d, attr.flags=0x%x, attr.tags=%s",
-            maxChannels, pAttributes->usage, pAttributes->flags, pAttributes->tags);
-
-    // check limits
-    mMaxChannels = maxChannels;
-    if (mMaxChannels < 1) {
-        mMaxChannels = 1;
-    }
-    else if (mMaxChannels > 32) {
-        mMaxChannels = 32;
-    }
-    ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels);
-
-    mQuit = false;
-    mDecodeThread = 0;
-    memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
-    mAllocated = 0;
-    mNextSampleID = 0;
-    mNextChannelID = 0;
-
-    mCallback = 0;
-    mUserData = 0;
-
-    mChannelPool = new SoundChannel[mMaxChannels];
-    for (int i = 0; i < mMaxChannels; ++i) {
-        mChannelPool[i].init(this);
-        mChannels.push_back(&mChannelPool[i]);
-    }
-
-    // start decode thread
-    startThreads();
-}
-
-SoundPool::~SoundPool()
-{
-    ALOGV("SoundPool destructor");
-    mDecodeThread->quit();
-    quit();
-
-    Mutex::Autolock lock(&mLock);
-
-    mChannels.clear();
-    if (mChannelPool)
-        delete [] mChannelPool;
-    // clean up samples
-    ALOGV("clear samples");
-    mSamples.clear();
-
-    if (mDecodeThread)
-        delete mDecodeThread;
-}
-
-void SoundPool::addToRestartList(SoundChannel* channel)
-{
-    Mutex::Autolock lock(&mRestartLock);
-    if (!mQuit) {
-        mRestart.push_back(channel);
-        mCondition.signal();
-    }
-}
-
-void SoundPool::addToStopList(SoundChannel* channel)
-{
-    Mutex::Autolock lock(&mRestartLock);
-    if (!mQuit) {
-        mStop.push_back(channel);
-        mCondition.signal();
-    }
-}
-
-int SoundPool::beginThread(void* arg)
-{
-    SoundPool* p = (SoundPool*)arg;
-    return p->run();
-}
-
-int SoundPool::run()
-{
-    mRestartLock.lock();
-    while (!mQuit) {
-        mCondition.wait(mRestartLock);
-        ALOGV("awake");
-        if (mQuit) break;
-
-        while (!mStop.empty()) {
-            SoundChannel* channel;
-            ALOGV("Getting channel from stop list");
-            List<SoundChannel* >::iterator iter = mStop.begin();
-            channel = *iter;
-            mStop.erase(iter);
-            mRestartLock.unlock();
-            if (channel != 0) {
-                Mutex::Autolock lock(&mLock);
-                channel->stop();
-            }
-            mRestartLock.lock();
-            if (mQuit) break;
-        }
-
-        while (!mRestart.empty()) {
-            SoundChannel* channel;
-            ALOGV("Getting channel from list");
-            List<SoundChannel*>::iterator iter = mRestart.begin();
-            channel = *iter;
-            mRestart.erase(iter);
-            mRestartLock.unlock();
-            if (channel != 0) {
-                Mutex::Autolock lock(&mLock);
-                channel->nextEvent();
-            }
-            mRestartLock.lock();
-            if (mQuit) break;
-        }
-    }
-
-    mStop.clear();
-    mRestart.clear();
-    mCondition.signal();
-    mRestartLock.unlock();
-    ALOGV("goodbye");
-    return 0;
-}
-
-void SoundPool::quit()
-{
-    mRestartLock.lock();
-    mQuit = true;
-    mCondition.signal();
-    mCondition.wait(mRestartLock);
-    ALOGV("return from quit");
-    mRestartLock.unlock();
-}
-
-bool SoundPool::startThreads()
-{
-    createThreadEtc(beginThread, this, "SoundPool");
-    if (mDecodeThread == NULL)
-        mDecodeThread = new SoundPoolThread(this);
-    return mDecodeThread != NULL;
-}
-
-SoundChannel* SoundPool::findChannel(int channelID)
-{
-    for (int i = 0; i < mMaxChannels; ++i) {
-        if (mChannelPool[i].channelID() == channelID) {
-            return &mChannelPool[i];
-        }
-    }
-    return NULL;
-}
-
-SoundChannel* SoundPool::findNextChannel(int channelID)
-{
-    for (int i = 0; i < mMaxChannels; ++i) {
-        if (mChannelPool[i].nextChannelID() == channelID) {
-            return &mChannelPool[i];
-        }
-    }
-    return NULL;
-}
-
-int SoundPool::load(const char* path, int priority __unused)
-{
-    ALOGV("load: path=%s, priority=%d", path, priority);
-    Mutex::Autolock lock(&mLock);
-    sp<Sample> sample = new Sample(++mNextSampleID, path);
-    mSamples.add(sample->sampleID(), sample);
-    doLoad(sample);
-    return sample->sampleID();
-}
-
-int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused)
-{
-    ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d",
-            fd, offset, length, priority);
-    Mutex::Autolock lock(&mLock);
-    sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length);
-    mSamples.add(sample->sampleID(), sample);
-    doLoad(sample);
-    return sample->sampleID();
-}
-
-void SoundPool::doLoad(sp<Sample>& sample)
-{
-    ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID());
-    sample->startLoad();
-    mDecodeThread->loadSample(sample->sampleID());
-}
-
-bool SoundPool::unload(int sampleID)
-{
-    ALOGV("unload: sampleID=%d", sampleID);
-    Mutex::Autolock lock(&mLock);
-    return mSamples.removeItem(sampleID);
-}
-
-int SoundPool::play(int sampleID, float leftVolume, float rightVolume,
-        int priority, int loop, float rate)
-{
-    ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
-            sampleID, leftVolume, rightVolume, priority, loop, rate);
-    sp<Sample> sample;
-    SoundChannel* channel;
-    int channelID;
-
-    Mutex::Autolock lock(&mLock);
-
-    if (mQuit) {
-        return 0;
-    }
-    // is sample ready?
-    sample = findSample(sampleID);
-    if ((sample == 0) || (sample->state() != Sample::READY)) {
-        ALOGW("  sample %d not READY", sampleID);
-        return 0;
-    }
-
-    dump();
-
-    // allocate a channel
-    channel = allocateChannel_l(priority);
-
-    // no channel allocated - return 0
-    if (!channel) {
-        ALOGV("No channel allocated");
-        return 0;
-    }
-
-    channelID = ++mNextChannelID;
-
-    ALOGV("play channel %p state = %d", channel, channel->state());
-    channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
-    return channelID;
-}
-
-SoundChannel* SoundPool::allocateChannel_l(int priority)
-{
-    List<SoundChannel*>::iterator iter;
-    SoundChannel* channel = NULL;
-
-    // allocate a channel
-    if (!mChannels.empty()) {
-        iter = mChannels.begin();
-        if (priority >= (*iter)->priority()) {
-            channel = *iter;
-            mChannels.erase(iter);
-            ALOGV("Allocated active channel");
-        }
-    }
-
-    // update priority and put it back in the list
-    if (channel) {
-        channel->setPriority(priority);
-        for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
-            if (priority < (*iter)->priority()) {
-                break;
-            }
-        }
-        mChannels.insert(iter, channel);
-    }
-    return channel;
-}
-
-// move a channel from its current position to the front of the list
-void SoundPool::moveToFront_l(SoundChannel* channel)
-{
-    for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
-        if (*iter == channel) {
-            mChannels.erase(iter);
-            mChannels.push_front(channel);
-            break;
-        }
-    }
-}
-
-void SoundPool::pause(int channelID)
-{
-    ALOGV("pause(%d)", channelID);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->pause();
-    }
-}
-
-void SoundPool::autoPause()
-{
-    ALOGV("autoPause()");
-    Mutex::Autolock lock(&mLock);
-    for (int i = 0; i < mMaxChannels; ++i) {
-        SoundChannel* channel = &mChannelPool[i];
-        channel->autoPause();
-    }
-}
-
-void SoundPool::resume(int channelID)
-{
-    ALOGV("resume(%d)", channelID);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->resume();
-    }
-}
-
-void SoundPool::autoResume()
-{
-    ALOGV("autoResume()");
-    Mutex::Autolock lock(&mLock);
-    for (int i = 0; i < mMaxChannels; ++i) {
-        SoundChannel* channel = &mChannelPool[i];
-        channel->autoResume();
-    }
-}
-
-void SoundPool::stop(int channelID)
-{
-    ALOGV("stop(%d)", channelID);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->stop();
-    } else {
-        channel = findNextChannel(channelID);
-        if (channel)
-            channel->clearNextEvent();
-    }
-}
-
-void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume)
-{
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setVolume(leftVolume, rightVolume);
-    }
-}
-
-void SoundPool::setPriority(int channelID, int priority)
-{
-    ALOGV("setPriority(%d, %d)", channelID, priority);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setPriority(priority);
-    }
-}
-
-void SoundPool::setLoop(int channelID, int loop)
-{
-    ALOGV("setLoop(%d, %d)", channelID, loop);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setLoop(loop);
-    }
-}
-
-void SoundPool::setRate(int channelID, float rate)
-{
-    ALOGV("setRate(%d, %f)", channelID, rate);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setRate(rate);
-    }
-}
-
-// call with lock held
-void SoundPool::done_l(SoundChannel* channel)
-{
-    ALOGV("done_l(%d)", channel->channelID());
-    // if "stolen", play next event
-    if (channel->nextChannelID() != 0) {
-        ALOGV("add to restart list");
-        addToRestartList(channel);
-    }
-
-    // return to idle state
-    else {
-        ALOGV("move to front");
-        moveToFront_l(channel);
-    }
-}
-
-void SoundPool::setCallback(SoundPoolCallback* callback, void* user)
-{
-    Mutex::Autolock lock(&mCallbackLock);
-    mCallback = callback;
-    mUserData = user;
-}
-
-void SoundPool::notify(SoundPoolEvent event)
-{
-    Mutex::Autolock lock(&mCallbackLock);
-    if (mCallback != NULL) {
-        mCallback(event, this, mUserData);
-    }
-}
-
-void SoundPool::dump()
-{
-    for (int i = 0; i < mMaxChannels; ++i) {
-        mChannelPool[i].dump();
-    }
-}
-
-
-Sample::Sample(int sampleID, const char* url)
-{
-    init();
-    mSampleID = sampleID;
-    mUrl = strdup(url);
-    ALOGV("create sampleID=%d, url=%s", mSampleID, mUrl);
-}
-
-Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length)
-{
-    init();
-    mSampleID = sampleID;
-    mFd = dup(fd);
-    mOffset = offset;
-    mLength = length;
-    ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64,
-        mSampleID, mFd, mLength, mOffset);
-}
-
-void Sample::init()
-{
-    mSize = 0;
-    mRefCount = 0;
-    mSampleID = 0;
-    mState = UNLOADED;
-    mFd = -1;
-    mOffset = 0;
-    mLength = 0;
-    mUrl = 0;
-}
-
-Sample::~Sample()
-{
-    ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd);
-    if (mFd > 0) {
-        ALOGV("close(%d)", mFd);
-        ::close(mFd);
-    }
-    free(mUrl);
-}
-
-status_t Sample::doLoad()
-{
-    uint32_t sampleRate;
-    int numChannels;
-    audio_format_t format;
-    status_t status;
-    mHeap = new MemoryHeapBase(kDefaultHeapSize);
-
-    ALOGV("Start decode");
-    if (mUrl) {
-        status = MediaPlayer::decode(
-                NULL /* httpService */,
-                mUrl,
-                &sampleRate,
-                &numChannels,
-                &format,
-                mHeap,
-                &mSize);
-    } else {
-        status = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format,
-                                     mHeap, &mSize);
-        ALOGV("close(%d)", mFd);
-        ::close(mFd);
-        mFd = -1;
-    }
-    if (status != NO_ERROR) {
-        ALOGE("Unable to load sample: %s", mUrl);
-        goto error;
-    }
-    ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d",
-          mHeap->getBase(), mSize, sampleRate, numChannels);
-
-    if (sampleRate > kMaxSampleRate) {
-       ALOGE("Sample rate (%u) out of range", sampleRate);
-       status = BAD_VALUE;
-       goto error;
-    }
-
-    if ((numChannels < 1) || (numChannels > 2)) {
-        ALOGE("Sample channel count (%d) out of range", numChannels);
-        status = BAD_VALUE;
-        goto error;
-    }
-
-    mData = new MemoryBase(mHeap, 0, mSize);
-    mSampleRate = sampleRate;
-    mNumChannels = numChannels;
-    mFormat = format;
-    mState = READY;
-    return NO_ERROR;
-
-error:
-    mHeap.clear();
-    return status;
-}
-
-
-void SoundChannel::init(SoundPool* soundPool)
-{
-    mSoundPool = soundPool;
-}
-
-// call with sound pool lock held
-void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
-        float rightVolume, int priority, int loop, float rate)
-{
-    sp<AudioTrack> oldTrack;
-    sp<AudioTrack> newTrack;
-    status_t status;
-
-    { // scope for the lock
-        Mutex::Autolock lock(&mLock);
-
-        ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f,"
-                " priority=%d, loop=%d, rate=%f",
-                this, sample->sampleID(), nextChannelID, leftVolume, rightVolume,
-                priority, loop, rate);
-
-        // if not idle, this voice is being stolen
-        if (mState != IDLE) {
-            ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
-            mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
-            stop_l();
-            return;
-        }
-
-        // initialize track
-        size_t afFrameCount;
-        uint32_t afSampleRate;
-        audio_stream_type_t streamType = audio_attributes_to_stream_type(mSoundPool->attributes());
-        if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
-            afFrameCount = kDefaultFrameCount;
-        }
-        if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
-            afSampleRate = kDefaultSampleRate;
-        }
-        int numChannels = sample->numChannels();
-        uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
-        uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
-        uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
-        size_t frameCount = 0;
-
-        if (loop) {
-            frameCount = sample->size()/numChannels/
-                ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
-        }
-
-#ifndef USE_SHARED_MEM_BUFFER
-        // Ensure minimum audio buffer size in case of short looped sample
-        if(frameCount < totalFrames) {
-            frameCount = totalFrames;
-        }
-#endif
-
-        // mToggle toggles each time a track is started on a given channel.
-        // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
-        // as callback user data. This enables the detection of callbacks received from the old
-        // audio track while the new one is being started and avoids processing them with
-        // wrong audio audio buffer size  (mAudioBufferSize)
-        unsigned long toggle = mToggle ^ 1;
-        void *userData = (void *)((unsigned long)this | toggle);
-        audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels);
-
-        // do not create a new audio track if current track is compatible with sample parameters
-#ifdef USE_SHARED_MEM_BUFFER
-        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-                channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData);
-#else
-        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-                channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
-                bufferFrames);
-#endif
-        oldTrack = mAudioTrack;
-        status = newTrack->initCheck();
-        if (status != NO_ERROR) {
-            ALOGE("Error creating AudioTrack");
-            goto exit;
-        }
-        ALOGV("setVolume %p", newTrack.get());
-        newTrack->setVolume(leftVolume, rightVolume);
-        newTrack->setLoop(0, frameCount, loop);
-
-        // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
-        mToggle = toggle;
-        mAudioTrack = newTrack;
-        mPos = 0;
-        mSample = sample;
-        mChannelID = nextChannelID;
-        mPriority = priority;
-        mLoop = loop;
-        mLeftVolume = leftVolume;
-        mRightVolume = rightVolume;
-        mNumChannels = numChannels;
-        mRate = rate;
-        clearNextEvent();
-        mState = PLAYING;
-        mAudioTrack->start();
-        mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
-    }
-
-exit:
-    ALOGV("delete oldTrack %p", oldTrack.get());
-    if (status != NO_ERROR) {
-        mAudioTrack.clear();
-    }
-}
-
-void SoundChannel::nextEvent()
-{
-    sp<Sample> sample;
-    int nextChannelID;
-    float leftVolume;
-    float rightVolume;
-    int priority;
-    int loop;
-    float rate;
-
-    // check for valid event
-    {
-        Mutex::Autolock lock(&mLock);
-        nextChannelID = mNextEvent.channelID();
-        if (nextChannelID  == 0) {
-            ALOGV("stolen channel has no event");
-            return;
-        }
-
-        sample = mNextEvent.sample();
-        leftVolume = mNextEvent.leftVolume();
-        rightVolume = mNextEvent.rightVolume();
-        priority = mNextEvent.priority();
-        loop = mNextEvent.loop();
-        rate = mNextEvent.rate();
-    }
-
-    ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID);
-    play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
-}
-
-void SoundChannel::callback(int event, void* user, void *info)
-{
-    SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1));
-
-    channel->process(event, info, (unsigned long)user & 1);
-}
-
-void SoundChannel::process(int event, void *info, unsigned long toggle)
-{
-    //ALOGV("process(%d)", mChannelID);
-
-    Mutex::Autolock lock(&mLock);
-
-    AudioTrack::Buffer* b = NULL;
-    if (event == AudioTrack::EVENT_MORE_DATA) {
-       b = static_cast<AudioTrack::Buffer *>(info);
-    }
-
-    if (mToggle != toggle) {
-        ALOGV("process wrong toggle %p channel %d", this, mChannelID);
-        if (b != NULL) {
-            b->size = 0;
-        }
-        return;
-    }
-
-    sp<Sample> sample = mSample;
-
-//    ALOGV("SoundChannel::process event %d", event);
-
-    if (event == AudioTrack::EVENT_MORE_DATA) {
-
-        // check for stop state
-        if (b->size == 0) return;
-
-        if (mState == IDLE) {
-            b->size = 0;
-            return;
-        }
-
-        if (sample != 0) {
-            // fill buffer
-            uint8_t* q = (uint8_t*) b->i8;
-            size_t count = 0;
-
-            if (mPos < (int)sample->size()) {
-                uint8_t* p = sample->data() + mPos;
-                count = sample->size() - mPos;
-                if (count > b->size) {
-                    count = b->size;
-                }
-                memcpy(q, p, count);
-//              ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size,
-//                      count);
-            } else if (mPos < mAudioBufferSize) {
-                count = mAudioBufferSize - mPos;
-                if (count > b->size) {
-                    count = b->size;
-                }
-                memset(q, 0, count);
-//              ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count);
-            }
-
-            mPos += count;
-            b->size = count;
-            //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]);
-        }
-    } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END ||
-            event == AudioTrack::EVENT_NEW_IAUDIOTRACK) {
-        ALOGV("process %p channel %d event %s",
-              this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" :
-                      (event == AudioTrack::EVENT_BUFFER_END) ? "BUFFER_END" : "NEW_IAUDIOTRACK");
-        mSoundPool->addToStopList(this);
-    } else if (event == AudioTrack::EVENT_LOOP_END) {
-        ALOGV("End loop %p channel %d", this, mChannelID);
-    } else {
-        ALOGW("SoundChannel::process unexpected event %d", event);
-    }
-}
-
-
-// call with lock held
-bool SoundChannel::doStop_l()
-{
-    if (mState != IDLE) {
-        setVolume_l(0, 0);
-        ALOGV("stop");
-        mAudioTrack->stop();
-        mSample.clear();
-        mState = IDLE;
-        mPriority = IDLE_PRIORITY;
-        return true;
-    }
-    return false;
-}
-
-// call with lock held and sound pool lock held
-void SoundChannel::stop_l()
-{
-    if (doStop_l()) {
-        mSoundPool->done_l(this);
-    }
-}
-
-// call with sound pool lock held
-void SoundChannel::stop()
-{
-    bool stopped;
-    {
-        Mutex::Autolock lock(&mLock);
-        stopped = doStop_l();
-    }
-
-    if (stopped) {
-        mSoundPool->done_l(this);
-    }
-}
-
-//FIXME: Pause is a little broken right now
-void SoundChannel::pause()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mState == PLAYING) {
-        ALOGV("pause track");
-        mState = PAUSED;
-        mAudioTrack->pause();
-    }
-}
-
-void SoundChannel::autoPause()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mState == PLAYING) {
-        ALOGV("pause track");
-        mState = PAUSED;
-        mAutoPaused = true;
-        mAudioTrack->pause();
-    }
-}
-
-void SoundChannel::resume()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mState == PAUSED) {
-        ALOGV("resume track");
-        mState = PLAYING;
-        mAutoPaused = false;
-        mAudioTrack->start();
-    }
-}
-
-void SoundChannel::autoResume()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mAutoPaused && (mState == PAUSED)) {
-        ALOGV("resume track");
-        mState = PLAYING;
-        mAutoPaused = false;
-        mAudioTrack->start();
-    }
-}
-
-void SoundChannel::setRate(float rate)
-{
-    Mutex::Autolock lock(&mLock);
-    if (mAudioTrack != NULL && mSample != 0) {
-        uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5);
-        mAudioTrack->setSampleRate(sampleRate);
-        mRate = rate;
-    }
-}
-
-// call with lock held
-void SoundChannel::setVolume_l(float leftVolume, float rightVolume)
-{
-    mLeftVolume = leftVolume;
-    mRightVolume = rightVolume;
-    if (mAudioTrack != NULL)
-        mAudioTrack->setVolume(leftVolume, rightVolume);
-}
-
-void SoundChannel::setVolume(float leftVolume, float rightVolume)
-{
-    Mutex::Autolock lock(&mLock);
-    setVolume_l(leftVolume, rightVolume);
-}
-
-void SoundChannel::setLoop(int loop)
-{
-    Mutex::Autolock lock(&mLock);
-    if (mAudioTrack != NULL && mSample != 0) {
-        uint32_t loopEnd = mSample->size()/mNumChannels/
-            ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
-        mAudioTrack->setLoop(0, loopEnd, loop);
-        mLoop = loop;
-    }
-}
-
-SoundChannel::~SoundChannel()
-{
-    ALOGV("SoundChannel destructor %p", this);
-    {
-        Mutex::Autolock lock(&mLock);
-        clearNextEvent();
-        doStop_l();
-    }
-    // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack
-    // callback thread to exit which may need to execute process() and acquire the mLock.
-    mAudioTrack.clear();
-}
-
-void SoundChannel::dump()
-{
-    ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d",
-            mState, mChannelID, mNumChannels, mPos, mPriority, mLoop);
-}
-
-void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume,
-            float rightVolume, int priority, int loop, float rate)
-{
-    mSample = sample;
-    mChannelID = channelID;
-    mLeftVolume = leftVolume;
-    mRightVolume = rightVolume;
-    mPriority = priority;
-    mLoop = loop;
-    mRate =rate;
-}
-
-} // end namespace android
diff --git a/media/libmedia/SoundPoolThread.cpp b/media/libmedia/SoundPoolThread.cpp
deleted file mode 100644
index ba3b482..0000000
--- a/media/libmedia/SoundPoolThread.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2007 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 "SoundPoolThread"
-#include "utils/Log.h"
-
-#include "SoundPoolThread.h"
-
-namespace android {
-
-void SoundPoolThread::write(SoundPoolMsg msg) {
-    Mutex::Autolock lock(&mLock);
-    while (mMsgQueue.size() >= maxMessages) {
-        mCondition.wait(mLock);
-    }
-
-    // if thread is quitting, don't add to queue
-    if (mRunning) {
-        mMsgQueue.push(msg);
-        mCondition.signal();
-    }
-}
-
-const SoundPoolMsg SoundPoolThread::read() {
-    Mutex::Autolock lock(&mLock);
-    while (mMsgQueue.size() == 0) {
-        mCondition.wait(mLock);
-    }
-    SoundPoolMsg msg = mMsgQueue[0];
-    mMsgQueue.removeAt(0);
-    mCondition.signal();
-    return msg;
-}
-
-void SoundPoolThread::quit() {
-    Mutex::Autolock lock(&mLock);
-    if (mRunning) {
-        mRunning = false;
-        mMsgQueue.clear();
-        mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
-        mCondition.signal();
-        mCondition.wait(mLock);
-    }
-    ALOGV("return from quit");
-}
-
-SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
-    mSoundPool(soundPool)
-{
-    mMsgQueue.setCapacity(maxMessages);
-    if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
-        mRunning = true;
-    }
-}
-
-SoundPoolThread::~SoundPoolThread()
-{
-    quit();
-}
-
-int SoundPoolThread::beginThread(void* arg) {
-    ALOGV("beginThread");
-    SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg;
-    return soundPoolThread->run();
-}
-
-int SoundPoolThread::run() {
-    ALOGV("run");
-    for (;;) {
-        SoundPoolMsg msg = read();
-        ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
-        switch (msg.mMessageType) {
-        case SoundPoolMsg::KILL:
-            ALOGV("goodbye");
-            return NO_ERROR;
-        case SoundPoolMsg::LOAD_SAMPLE:
-            doLoadSample(msg.mData);
-            break;
-        default:
-            ALOGW("run: Unrecognized message %d\n",
-                    msg.mMessageType);
-            break;
-        }
-    }
-}
-
-void SoundPoolThread::loadSample(int sampleID) {
-    write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID));
-}
-
-void SoundPoolThread::doLoadSample(int sampleID) {
-    sp <Sample> sample = mSoundPool->findSample(sampleID);
-    status_t status = -1;
-    if (sample != 0) {
-        status = sample->doLoad();
-    }
-    mSoundPool->notify(SoundPoolEvent(SoundPoolEvent::SAMPLE_LOADED, sampleID, status));
-}
-
-} // end namespace android
diff --git a/media/libmedia/SoundPoolThread.h b/media/libmedia/SoundPoolThread.h
deleted file mode 100644
index 7e96900..0000000
--- a/media/libmedia/SoundPoolThread.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007 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 SOUNDPOOLTHREAD_H_
-#define SOUNDPOOLTHREAD_H_
-
-#include <utils/threads.h>
-#include <utils/Vector.h>
-#include <media/AudioTrack.h>
-
-#include <media/SoundPool.h>
-
-namespace android {
-
-class SoundPoolMsg {
-public:
-    enum MessageType { INVALID, KILL, LOAD_SAMPLE };
-    SoundPoolMsg() : mMessageType(INVALID), mData(0) {}
-    SoundPoolMsg(MessageType MessageType, int data) :
-        mMessageType(MessageType), mData(data) {}
-    uint16_t         mMessageType;
-    uint16_t         mData;
-};
-
-/*
- * This class handles background requests from the SoundPool
- */
-class SoundPoolThread {
-public:
-    SoundPoolThread(SoundPool* SoundPool);
-    ~SoundPoolThread();
-    void loadSample(int sampleID);
-    void quit();
-    void write(SoundPoolMsg msg);
-
-private:
-    static const size_t maxMessages = 5;
-
-    static int beginThread(void* arg);
-    int run();
-    void doLoadSample(int sampleID);
-    const SoundPoolMsg read();
-
-    Mutex                   mLock;
-    Condition               mCondition;
-    Vector<SoundPoolMsg>    mMsgQueue;
-    SoundPool*              mSoundPool;
-    bool                    mRunning;
-};
-
-} // end namespace android
-
-#endif /*SOUNDPOOLTHREAD_H_*/
diff --git a/media/libmedia/StringArray.cpp b/media/libmedia/StringArray.cpp
index 5f5b57a..477e3fd 100644
--- a/media/libmedia/StringArray.cpp
+++ b/media/libmedia/StringArray.cpp
@@ -16,7 +16,7 @@
 
 //
 // Sortable array of strings.  STL-ish, but STL-free.
-//  
+//
 
 #include <stdlib.h>
 #include <string.h>
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 61b6d36..2cc4685 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -28,718 +28,718 @@
 
 // Descriptors for all available tones (See ToneGenerator::ToneDescriptor class declaration for details)
 const ToneGenerator::ToneDescriptor ToneGenerator::sToneDescriptors[] = {
-        { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 941, 0 }, 0, 0},
-                     { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_0
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 697, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_1
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 697, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_2
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 697, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_3
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 770, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_4
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 770, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_5
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 770, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_6
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 852, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_7
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 852, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_8
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 852, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_9
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 941, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_S
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 941, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_P
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 697, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_A
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 770, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                             // TONE_DTMF_B
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 852, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_C
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 941, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_DTMF_D
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_SUP_DIAL
-        { segments: { { duration: 500 , waveFreq: { 425, 0 }, 0, 0},
-                      { duration: 500, waveFreq: { 0 }, 0, 0},
-                         { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_SUP_BUSY
-        { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_SUP_CONGESTION
-        { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 0,
-          repeatSegment: 0 },                              // TONE_SUP_RADIO_ACK
-        { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0},
-                      { duration: 200, waveFreq: { 0 }, 0, 0},
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 2,
-          repeatSegment: 0 },                              // TONE_SUP_RADIO_NOTAVAIL
-        { segments: { { duration: 330, waveFreq: { 950, 1400, 1800, 0 }, 0, 0},
-                      { duration: 1000, waveFreq: { 0 }, 0, 0},
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_SUP_ERROR
-        { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
-                      { duration: 600, waveFreq: { 0 }, 0, 0 },
-                      { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
-                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_SUP_CALL_WAITING
-        { segments: { { duration: 1000, waveFreq: { 425, 0 }, 0, 0 },
-                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_SUP_RINGTONE
-        { segments: { { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 0,
-          repeatSegment: 0 },                              // TONE_PROP_BEEP
-        { segments: { { duration: 100, waveFreq: { 1200, 0 }, 0, 0 },
-                      { duration: 100, waveFreq: { 0 }, 0, 0  },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 1,
-          repeatSegment: 0 },                              // TONE_PROP_ACK
-        { segments: { { duration: 400, waveFreq: { 300, 400, 500, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 0,
-          repeatSegment: 0 },                              // TONE_PROP_NACK
-        { segments: { { duration: 200, waveFreq: { 400, 1200, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 0,
-          repeatSegment: 0 },                              // TONE_PROP_PROMPT
-        { segments: { { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 0,
-          repeatSegment: 0 },                             // TONE_PROP_BEEP2
-        { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
-                      { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_SUP_INTERCEPT
-        { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
-                      { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 7,
-          repeatSegment: 0 },                             // TONE_SUP_INTERCEPT_ABBREV
-        { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
-                      { duration: 250, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 7,
-          repeatSegment: 0 },                             // TONE_SUP_CONGESTION_ABBREV
-        { segments: { { duration: 100, waveFreq: { 350, 440, 0 }, 0, 0 },
-                      { duration: 100, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 2,
-          repeatSegment: 0 },                             // TONE_SUP_CONFIRM
-        { segments: { { duration: 100, waveFreq: { 480, 0 }, 0, 0 },
-                      { duration: 100, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 3,
-          repeatSegment: 0 },                              // TONE_SUP_PIP
-        { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 }, 0, 0},
-                     { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_CDMA_DIAL_TONE_LITE
-        { segments: { { duration: 2000, waveFreq: { 440, 480, 0 }, 0, 0 },
-                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_CDMA_NETWORK_USA_RINGBACK
-        { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
-                      { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt:  ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                             // TONE_CDMA_INTERCEPT
-        { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
-                      { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt:  0,
-          repeatSegment: 0 },                             // TONE_CDMA_ABBR_INTERCEPT
-        { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
-                      { duration: 250, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_CDMA_REORDER
-        { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
-                      { duration: 250, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 7,
-          repeatSegment: 0 },                              // TONE_CDMA_ABBR_REORDER
-        { segments: { { duration: 500, waveFreq: { 480, 620, 0 }, 0, 0 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_CDMA_NETWORK_BUSY
-        { segments: { { duration: 100, waveFreq: { 350, 440, 0 }, 0, 0 },
-                      { duration: 100, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 2,
-          repeatSegment: 0 },                              // TONE_CDMA_CONFIRM
-        { segments: { { duration: 500, waveFreq: { 660, 1000, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 0,
-          repeatSegment: 0 },                              // TONE_CDMA_ANSWER
-        { segments: { { duration: 300, waveFreq: { 440, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 0,
-          repeatSegment: 0 },                              // TONE_CDMA_NETWORK_CALLWAITING
-        { segments: { { duration: 100, waveFreq: { 480, 0 }, 0, 0 },
-                      { duration: 100, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 3,
-          repeatSegment: 0 },                              // TONE_CDMA_PIP
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1336, 941, 0 }, 0, 0},
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_0
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1209, 697, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_1
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1336, 697, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_2
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1477, 697, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_3
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1209, 770, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_4
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1336, 770, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_5
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1477, 770, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_6
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1209, 852, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_7
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1336, 852, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_8
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1477, 852, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_9
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1209, 941, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_S
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1477, 941, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_P
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1633, 697, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_A
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1633, 770, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                             // TONE_DTMF_B
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1633, 852, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_C
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 1633, 941, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_DTMF_D
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 425, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_SUP_DIAL
+        { .segments = { { .duration = 500 , .waveFreq = { 425, 0 }, 0, 0},
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0},
+                           { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_SUP_BUSY
+        { .segments = { { .duration = 200, .waveFreq = { 425, 0 }, 0, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_SUP_CONGESTION
+        { .segments = { { .duration = 200, .waveFreq = { 425, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                              // TONE_SUP_RADIO_ACK
+        { .segments = { { .duration = 200, .waveFreq = { 425, 0 }, 0, 0},
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0},
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 2,
+          .repeatSegment = 0 },                              // TONE_SUP_RADIO_NOTAVAIL
+        { .segments = { { .duration = 330, .waveFreq = { 950, 1400, 1800, 0 }, 0, 0},
+                        { .duration = 1000, .waveFreq = { 0 }, 0, 0},
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_SUP_ERROR
+        { .segments = { { .duration = 200, .waveFreq = { 425, 0 }, 0, 0 },
+                        { .duration = 600, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 200, .waveFreq = { 425, 0 }, 0, 0 },
+                        { .duration = 3000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_SUP_CALL_WAITING
+        { .segments = { { .duration = 1000, .waveFreq = { 425, 0 }, 0, 0 },
+                        { .duration = 4000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_SUP_RINGTONE
+        { .segments = { { .duration = 40, .waveFreq = { 400, 1200, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                              // TONE_PROP_BEEP
+        { .segments = { { .duration = 100, .waveFreq = { 1200, 0 }, 0, 0 },
+                        { .duration = 100, .waveFreq = { 0 }, 0, 0  },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 1,
+          .repeatSegment = 0 },                              // TONE_PROP_ACK
+        { .segments = { { .duration = 400, .waveFreq = { 300, 400, 500, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                              // TONE_PROP_NACK
+        { .segments = { { .duration = 200, .waveFreq = { 400, 1200, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                              // TONE_PROP_PROMPT
+        { .segments = { { .duration = 40, .waveFreq = { 400, 1200, 0 }, 0, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 40, .waveFreq = { 400, 1200, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                             // TONE_PROP_BEEP2
+        { .segments = { { .duration = 250, .waveFreq = { 440, 0 }, 0, 0 },
+                        { .duration = 250, .waveFreq = { 620, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_SUP_INTERCEPT
+        { .segments = { { .duration = 250, .waveFreq = { 440, 0 }, 0, 0 },
+                        { .duration = 250, .waveFreq = { 620, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 7,
+          .repeatSegment = 0 },                             // TONE_SUP_INTERCEPT_ABBREV
+        { .segments = { { .duration = 250, .waveFreq = { 480, 620, 0 }, 0, 0 },
+                        { .duration = 250, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 7,
+          .repeatSegment = 0 },                             // TONE_SUP_CONGESTION_ABBREV
+        { .segments = { { .duration = 100, .waveFreq = { 350, 440, 0 }, 0, 0 },
+                        { .duration = 100, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 2,
+          .repeatSegment = 0 },                             // TONE_SUP_CONFIRM
+        { .segments = { { .duration = 100, .waveFreq = { 480, 0 }, 0, 0 },
+                        { .duration = 100, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 3,
+          .repeatSegment = 0 },                              // TONE_SUP_PIP
+        { .segments = {{ .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 425, 0 }, 0, 0},
+                       { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_CDMA_DIAL_TONE_LITE
+        { .segments = { { .duration = 2000, .waveFreq = { 440, 480, 0 }, 0, 0 },
+                        { .duration = 4000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_CDMA_NETWORK_USA_RINGBACK
+        { .segments = { { .duration = 250, .waveFreq = { 440, 0 }, 0, 0 },
+                        { .duration = 250, .waveFreq = { 620, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt =  ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                             // TONE_CDMA_INTERCEPT
+        { .segments = { { .duration = 250, .waveFreq = { 440, 0 }, 0, 0 },
+                        { .duration = 250, .waveFreq = { 620, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt =  0,
+          .repeatSegment = 0 },                             // TONE_CDMA_ABBR_INTERCEPT
+        { .segments = { { .duration = 250, .waveFreq = { 480, 620, 0 }, 0, 0 },
+                        { .duration = 250, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_CDMA_REORDER
+        { .segments = { { .duration = 250, .waveFreq = { 480, 620, 0 }, 0, 0 },
+                        { .duration = 250, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 7,
+          .repeatSegment = 0 },                              // TONE_CDMA_ABBR_REORDER
+        { .segments = { { .duration = 500, .waveFreq = { 480, 620, 0 }, 0, 0 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_CDMA_NETWORK_BUSY
+        { .segments = { { .duration = 100, .waveFreq = { 350, 440, 0 }, 0, 0 },
+                        { .duration = 100, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 2,
+          .repeatSegment = 0 },                              // TONE_CDMA_CONFIRM
+        { .segments = { { .duration = 500, .waveFreq = { 660, 1000, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                              // TONE_CDMA_ANSWER
+        { .segments = { { .duration = 300, .waveFreq = { 440, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                              // TONE_CDMA_NETWORK_CALLWAITING
+        { .segments = { { .duration = 100, .waveFreq = { 480, 0 }, 0, 0 },
+                        { .duration = 100, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 3,
+          .repeatSegment = 0 },                              // TONE_CDMA_PIP
 
-        { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
-                      { duration: 64, waveFreq: { 2556, 0}, 19, 0},
-                      { duration: 32, waveFreq: { 2091, 0}, 0, 0},
-                      { duration: 48, waveFreq: { 2556, 0}, 0, 0},
-                      { duration: 4000, waveFreq: { 0 }, 0, 0},
-                      { duration: 0,  waveFreq: { 0 }, 0, 0}},
-          repeatCnt: 0,
-          repeatSegment: 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL
-        { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
-                      { duration: 64, waveFreq: { 2556, 0}, 7, 0 },
-                      { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
-                      { duration: 400, waveFreq: { 0 }, 0, 0 },
-                      { duration: 32,  waveFreq: { 2091, 0}, 0, 0 },
-                      { duration: 64,  waveFreq: { 2556, 0}, 7, 4 },
-                      { duration: 32,  waveFreq: { 2091, 0}, 0, 0 },
-                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0,    waveFreq: { 0 }, 0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                              // TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP
-        { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
-                      { duration: 64, waveFreq: { 2556, 0}, 3, 0 },
-                      { duration: 16, waveFreq: { 2091, 0}, 0, 0 },
-                      { duration: 200, waveFreq: { 0 },     0, 0 },
-                      { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
-                      { duration: 64, waveFreq: { 2556, 0}, 3, 4 },
-                      { duration: 16, waveFreq: { 2091, 0}, 0, 0 },
-                      { duration: 200, waveFreq: { 0 },     0, 0 },
-                      { duration: 0,   waveFreq: { 0 },     0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                            // TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI
-        { segments: { { duration: 0,  waveFreq: { 0 }, 0, 0} },
-          repeatCnt: 0,
-          repeatSegment: 0 },                            // TONE_CDMA_CALL_SIGNAL_ISDN_PAT3
-        { segments: { { duration: 32, waveFreq: { 2091, 0 }, 0, 0 },
-                      { duration: 64, waveFreq: { 2556, 0 }, 4, 0 },
-                      { duration: 20, waveFreq: { 2091, 0 }, 0, 0 },
-                      { duration: 0,  waveFreq: { 0 }      , 0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING
-        { segments: { { duration: 0,  waveFreq: { 0 }, 0, 0} },
-          repeatCnt: 0,
-          repeatSegment: 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PAT5
-        { segments: { { duration: 0,  waveFreq: { 0 }, 0, 0} },
-          repeatCnt: 0,
-          repeatSegment: 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PAT6
-        { segments: { { duration: 0,  waveFreq: { 0 }, 0, 0} },
-          repeatCnt: 0,
-          repeatSegment: 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PAT7
+        { .segments = { { .duration = 32, .waveFreq = { 2091, 0}, 0, 0 },
+                        { .duration = 64, .waveFreq = { 2556, 0}, 19, 0},
+                        { .duration = 32, .waveFreq = { 2091, 0}, 0, 0},
+                        { .duration = 48, .waveFreq = { 2556, 0}, 0, 0},
+                        { .duration = 4000, .waveFreq = { 0 }, 0, 0},
+                        { .duration = 0,  .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL
+        { .segments = { { .duration = 32, .waveFreq = { 2091, 0}, 0, 0 },
+                        { .duration = 64, .waveFreq = { 2556, 0}, 7, 0 },
+                        { .duration = 32, .waveFreq = { 2091, 0}, 0, 0 },
+                        { .duration = 400, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 32,  .waveFreq = { 2091, 0}, 0, 0 },
+                        { .duration = 64,  .waveFreq = { 2556, 0}, 7, 4 },
+                        { .duration = 32,  .waveFreq = { 2091, 0}, 0, 0 },
+                        { .duration = 4000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0,    .waveFreq = { 0 }, 0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                              // TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP
+        { .segments = { { .duration = 32, .waveFreq = { 2091, 0}, 0, 0 },
+                        { .duration = 64, .waveFreq = { 2556, 0}, 3, 0 },
+                        { .duration = 16, .waveFreq = { 2091, 0}, 0, 0 },
+                        { .duration = 200, .waveFreq = { 0 },     0, 0 },
+                        { .duration = 32, .waveFreq = { 2091, 0}, 0, 0 },
+                        { .duration = 64, .waveFreq = { 2556, 0}, 3, 4 },
+                        { .duration = 16, .waveFreq = { 2091, 0}, 0, 0 },
+                        { .duration = 200, .waveFreq = { 0 },     0, 0 },
+                        { .duration = 0,   .waveFreq = { 0 },     0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                            // TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI
+        { .segments = { { .duration = 0,  .waveFreq = { 0 }, 0, 0} },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                            // TONE_CDMA_CALL_SIGNAL_ISDN_PAT3
+        { .segments = { { .duration = 32, .waveFreq = { 2091, 0 }, 0, 0 },
+                        { .duration = 64, .waveFreq = { 2556, 0 }, 4, 0 },
+                        { .duration = 20, .waveFreq = { 2091, 0 }, 0, 0 },
+                        { .duration = 0,  .waveFreq = { 0 }      , 0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING
+        { .segments = { { .duration = 0,  .waveFreq = { 0 }, 0, 0} },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PAT5
+        { .segments = { { .duration = 0,  .waveFreq = { 0 }, 0, 0} },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PAT6
+        { .segments = { { .duration = 0,  .waveFreq = { 0 }, 0, 0} },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PAT7
 
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 39, 0 },
-                      { duration: 4000, waveFreq: { 0 },     0, 0 },
-                      { duration: 0,    waveFreq: { 0 },     0, 0 } },
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_L
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 39, 0 },
-                      { duration: 4000, waveFreq: { 0 },     0, 0 },
-                      { duration: 0,    waveFreq: { 0 },     0, 0 } },
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_L
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 39, 0 },
-                      { duration: 4000, waveFreq: { 0 },     0, 0 },
-                      { duration: 0,    waveFreq: { 0 },     0, 0 } },
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_L
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 15, 0 },
-                      { duration: 400, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 } },
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_SS
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 15, 0 },
-                      { duration: 400, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_SS
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 15, 0 },
-                      { duration: 400, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_SS
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 15, 6 },
-                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_SSL
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 15, 6 },
-                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_SSL
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 15, 6 },
-                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_SSL
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 19, 0 },
-                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 19, 3 },
-                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_SS_2
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 19, 0 },
-                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 19, 3 },
-                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_SS_2
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 19, 0 },
-                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 19, 3 },
-                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_SS_2
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 9, 0 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 19, 3 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 9, 6 },
-                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_SLS
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 9, 0 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 19, 3 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 9, 6 },
-                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_SLS
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 9, 0 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 19, 3 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 9, 6 },
-                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_SLS
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 9, 0 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 9, 3 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 9, 6 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 9, 9 },
-                      { duration: 2500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_S_X4
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 9, 0 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 9, 3 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 9, 6 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 9, 9 },
-                      { duration: 2500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_S_X4
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 9, 0 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 9, 3 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 9, 6 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 9, 9 },
-                      { duration: 2500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_S_X4
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 19, 0 },
-                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_PBX_L
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 19, 0 },
-                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_PBX_L
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 19, 0 },
-                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_PBX_L
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
-                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_PBX_SS
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
-                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_PBX_SS
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
-                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_PBX_SS
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 15, 6 },
-                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_PBX_SSL
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 15, 6 },
-                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_PBX_SSL
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 15, 6 },
-                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_PBX_SSL
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 15, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 6 },
-                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_PBX_SLS
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 15, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 6 },
-                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_PBX_SLS
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 15, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 6 },
-                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_PBX_SLS
-        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 6 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 4000, 0 }, 7, 9 },
-                      { duration: 800, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_HIGH_PBX_S_X4
-        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 6 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 2900, 0 }, 7, 9 },
-                      { duration: 800, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_MED_PBX_S_X4
-        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 6 },
-                      { duration: 200, waveFreq: { 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
-                      { duration: 25, waveFreq: { 1450, 0 }, 7, 9 },
-                      { duration: 800, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                           // TONE_CDMA_LOW_PBX_S_X4
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 39, 0 },
+                        { .duration = 4000, .waveFreq = { 0 },     0, 0 },
+                        { .duration = 0,    .waveFreq = { 0 },     0, 0 } },
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_L
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 39, 0 },
+                        { .duration = 4000, .waveFreq = { 0 },     0, 0 },
+                        { .duration = 0,    .waveFreq = { 0 },     0, 0 } },
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_L
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 39, 0 },
+                        { .duration = 4000, .waveFreq = { 0 },     0, 0 },
+                        { .duration = 0,    .waveFreq = { 0 },     0, 0 } },
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_L
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 15, 0 },
+                        { .duration = 400, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 } },
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_SS
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 15, 0 },
+                        { .duration = 400, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_SS
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 15, 0 },
+                        { .duration = 400, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_SS
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 15, 6 },
+                        { .duration = 4000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_SSL
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 15, 6 },
+                        { .duration = 4000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_SSL
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 15, 6 },
+                        { .duration = 4000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_SSL
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                          { .duration = 25, .waveFreq = { 4000, 0 }, 19, 0 },
+                        { .duration = 1000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 19, 3 },
+                        { .duration = 3000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_SS_2
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 19, 0 },
+                        { .duration = 1000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 19, 3 },
+                        { .duration = 3000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_SS_2
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 19, 0 },
+                        { .duration = 1000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 19, 3 },
+                        { .duration = 3000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_SS_2
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 9, 0 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 19, 3 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 9, 6 },
+                        { .duration = 3000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_SLS
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 9, 0 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 19, 3 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 9, 6 },
+                        { .duration = 3000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_SLS
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 9, 0 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 19, 3 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 9, 6 },
+                        { .duration = 3000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_SLS
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 9, 0 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 9, 3 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 9, 6 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 9, 9 },
+                        { .duration = 2500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_S_X4
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 9, 0 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 9, 3 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 9, 6 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 9, 9 },
+                        { .duration = 2500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_S_X4
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 9, 0 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 9, 3 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 9, 6 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 9, 9 },
+                        { .duration = 2500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_S_X4
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 19, 0 },
+                        { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_PBX_L
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 19, 0 },
+                        { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_PBX_L
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 19, 0 },
+                        { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_PBX_L
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 3 },
+                        { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_PBX_SS
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 3 },
+                        { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_PBX_SS
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 3 },
+                        { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_PBX_SS
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 15, 6 },
+                        { .duration = 1000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_PBX_SSL
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 15, 6 },
+                        { .duration = 1000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_PBX_SSL
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 15, 6 },
+                        { .duration = 1000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_PBX_SSL
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 15, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 6 },
+                        { .duration = 1000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_PBX_SLS
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 15, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 6 },
+                        { .duration = 1000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_PBX_SLS
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 15, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 6 },
+                        { .duration = 1000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+           .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_PBX_SLS
+        { .segments = { { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 6 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 3700, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 4000, 0 }, 7, 9 },
+                        { .duration = 800, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_HIGH_PBX_S_X4
+        { .segments = { { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 6 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2600, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 2900, 0 }, 7, 9 },
+                        { .duration = 800, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_MED_PBX_S_X4
+        { .segments = { { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 0 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 3 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 6 },
+                        { .duration = 200, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1300, 0 }, 0, 0 },
+                        { .duration = 25, .waveFreq = { 1450, 0 }, 7, 9 },
+                        { .duration = 800, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                           // TONE_CDMA_LOW_PBX_S_X4
 
-        { segments: { { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
-                      { duration: 62, waveFreq: { 784, 0 },  0, 0 },
-                      { duration: 62, waveFreq: { 740, 0 },  0, 0 },
-                      { duration: 62, waveFreq: { 622, 0 },  0, 0 },
-                      { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
-                      { duration: 0,  waveFreq: { 0 },       0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                            // TONE_CDMA_ALERT_NETWORK_LITE
-        { segments: { { duration: 62, waveFreq: { 1245, 0 }, 0, 0 },
-                      { duration: 62, waveFreq: { 659, 0 },  2, 0 },
-                      { duration: 62, waveFreq: { 1245, 0 }, 0, 0 },
-                      { duration: 0,  waveFreq: { 0 },       0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                            // TONE_CDMA_ALERT_AUTOREDIAL_LITE
-        { segments: { { duration: 400, waveFreq: { 1150, 770, 0 }, 0, 0 },
-                      { duration: 0,   waveFreq: { 0 },            0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                            // TONE_CDMA_ONE_MIN_BEEP
-        { segments: { { duration: 120, waveFreq: { 941, 1477, 0 }, 0, 0 },
-                      { duration: 0,   waveFreq: { 0 },            0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                            // TONE_CDMA_KEYPAD_VOLUME_KEY_LITE
-        { segments: { { duration: 375, waveFreq: { 587, 0 }, 0, 0 },
-                      { duration: 125, waveFreq: { 1175, 0 }, 0, 0 },
-                      { duration: 0,   waveFreq: { 0 },       0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                            // TONE_CDMA_PRESSHOLDKEY_LITE
-        { segments: { { duration: 62, waveFreq: { 587, 0 }, 0, 0 },
-                      { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
-                      { duration: 62, waveFreq: { 831, 0 }, 0, 0 },
-                      { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
-                      { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
-                      { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
-                      { duration: 62, waveFreq: { 831, 0 }, 0, 0 },
-                      { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
-                      { duration: 0,  waveFreq: { 0 },      0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                             // TONE_CDMA_ALERT_INCALL_LITE
-        { segments: { { duration: 125, waveFreq: { 941, 0 }, 0, 0 },
-                      { duration: 10,  waveFreq: { 0 },      2, 0 },
-                      { duration: 4990, waveFreq: { 0 },     0, 0 },
-                      { duration: 0,    waveFreq: { 0 },     0, 0 } },
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                            // TONE_CDMA_EMERGENCY_RINGBACK
-        { segments: { { duration: 125, waveFreq: { 1319, 0 }, 0, 0 },
-                      { duration: 125, waveFreq: { 0 },       0, 0 },
-                      { duration: 0,   waveFreq: { 0 },       0, 0 } },
-          repeatCnt: 2,
-          repeatSegment: 0 },                            // TONE_CDMA_ALERT_CALL_GUARD
-        { segments: { { duration: 125, waveFreq: { 1047, 0 }, 0, 0 },
-                      { duration: 125, waveFreq: { 370,  0 }, 0, 0 },
-                      { duration: 0,   waveFreq: { 0 },       0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                            // TONE_CDMA_SOFT_ERROR_LITE
-        { segments: { { duration: 125, waveFreq: { 1480, 0 }, 0, 0 },
-                      { duration: 125, waveFreq: { 1397, 0 }, 0, 0 },
-                      { duration: 125, waveFreq: { 784, 0 },  0, 0 },
-                      { duration: 0,   waveFreq: { 0 },       0, 0 } },
-          repeatCnt: 0,
-          repeatSegment: 0 },                            // TONE_CDMA_CALLDROP_LITE
+        { .segments = { { .duration = 62, .waveFreq = { 1109, 0 }, 0, 0 },
+                        { .duration = 62, .waveFreq = { 784, 0 },  0, 0 },
+                        { .duration = 62, .waveFreq = { 740, 0 },  0, 0 },
+                        { .duration = 62, .waveFreq = { 622, 0 },  0, 0 },
+                        { .duration = 62, .waveFreq = { 1109, 0 }, 0, 0 },
+                        { .duration = 0,  .waveFreq = { 0 },       0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                            // TONE_CDMA_ALERT_NETWORK_LITE
+        { .segments = { { .duration = 62, .waveFreq = { 1245, 0 }, 0, 0 },
+                        { .duration = 62, .waveFreq = { 659, 0 },  2, 0 },
+                        { .duration = 62, .waveFreq = { 1245, 0 }, 0, 0 },
+                        { .duration = 0,  .waveFreq = { 0 },       0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                            // TONE_CDMA_ALERT_AUTOREDIAL_LITE
+        { .segments = { { .duration = 400, .waveFreq = { 1150, 770, 0 }, 0, 0 },
+                        { .duration = 0,   .waveFreq = { 0 },            0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                            // TONE_CDMA_ONE_MIN_BEEP
+        { .segments = { { .duration = 120, .waveFreq = { 941, 1477, 0 }, 0, 0 },
+                        { .duration = 0,   .waveFreq = { 0 },            0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                            // TONE_CDMA_KEYPAD_VOLUME_KEY_LITE
+        { .segments = { { .duration = 375, .waveFreq = { 587, 0 }, 0, 0 },
+                        { .duration = 125, .waveFreq = { 1175, 0 }, 0, 0 },
+                        { .duration = 0,   .waveFreq = { 0 },       0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                            // TONE_CDMA_PRESSHOLDKEY_LITE
+        { .segments = { { .duration = 62, .waveFreq = { 587, 0 }, 0, 0 },
+                        { .duration = 62, .waveFreq = { 784, 0 }, 0, 0 },
+                        { .duration = 62, .waveFreq = { 831, 0 }, 0, 0 },
+                        { .duration = 62, .waveFreq = { 784, 0 }, 0, 0 },
+                        { .duration = 62, .waveFreq = { 1109, 0 }, 0, 0 },
+                        { .duration = 62, .waveFreq = { 784, 0 }, 0, 0 },
+                        { .duration = 62, .waveFreq = { 831, 0 }, 0, 0 },
+                        { .duration = 62, .waveFreq = { 784, 0 }, 0, 0 },
+                        { .duration = 0,  .waveFreq = { 0 },      0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                             // TONE_CDMA_ALERT_INCALL_LITE
+        { .segments = { { .duration = 125, .waveFreq = { 941, 0 }, 0, 0 },
+                        { .duration = 10,  .waveFreq = { 0 },      2, 0 },
+                        { .duration = 4990, .waveFreq = { 0 },     0, 0 },
+                        { .duration = 0,    .waveFreq = { 0 },     0, 0 } },
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                            // TONE_CDMA_EMERGENCY_RINGBACK
+        { .segments = { { .duration = 125, .waveFreq = { 1319, 0 }, 0, 0 },
+                        { .duration = 125, .waveFreq = { 0 },       0, 0 },
+                        { .duration = 0,   .waveFreq = { 0 },       0, 0 } },
+          .repeatCnt = 2,
+          .repeatSegment = 0 },                            // TONE_CDMA_ALERT_CALL_GUARD
+        { .segments = { { .duration = 125, .waveFreq = { 1047, 0 }, 0, 0 },
+                        { .duration = 125, .waveFreq = { 370,  0 }, 0, 0 },
+                        { .duration = 0,   .waveFreq = { 0 },       0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                            // TONE_CDMA_SOFT_ERROR_LITE
+        { .segments = { { .duration = 125, .waveFreq = { 1480, 0 }, 0, 0 },
+                        { .duration = 125, .waveFreq = { 1397, 0 }, 0, 0 },
+                        { .duration = 125, .waveFreq = { 784, 0 },  0, 0 },
+                        { .duration = 0,   .waveFreq = { 0 },       0, 0 } },
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                            // TONE_CDMA_CALLDROP_LITE
 
-        { segments: { { duration: 500, waveFreq: { 425, 0 }, 0, 0 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: 0,
-          repeatSegment: 0 },                           // TONE_CDMA_NETWORK_BUSY_ONE_SHOT
-        { segments: { { duration: 400, waveFreq: { 1150, 770 }, 0, 0 },
-                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: 0,
-          repeatSegment: 0 },                           // TONE_CDMA_ABBR_ALERT
-          { segments: { { duration: 0, waveFreq: { 0 }, 0, 0 }},
-          repeatCnt: 0,
-          repeatSegment: 0 },                            // TONE_CDMA_SIGNAL_OFF
+        { .segments = { { .duration = 500, .waveFreq = { 425, 0 }, 0, 0 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                           // TONE_CDMA_NETWORK_BUSY_ONE_SHOT
+        { .segments = { { .duration = 400, .waveFreq = { 1150, 770 }, 0, 0 },
+                        { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                           // TONE_CDMA_ABBR_ALERT
+          { .segments = { { .duration = 0, .waveFreq = { 0 }, 0, 0 }},
+          .repeatCnt = 0,
+          .repeatSegment = 0 },                            // TONE_CDMA_SIGNAL_OFF
 
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 350, 440, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_ANSI_DIAL
-        { segments: { { duration: 500, waveFreq: { 480, 620, 0 }, 0, 0 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_ANSI_BUSY
-        { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
-                      { duration: 250, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_ANSI_CONGESTION
-        { segments: { { duration: 300, waveFreq: { 440, 0 }, 0, 0 },
-                      { duration: 9700, waveFreq: { 0 }, 0, 0 },
-                      { duration: 100, waveFreq: { 440, 0 }, 0, 0 },
-                      { duration: 100, waveFreq: { 0 }, 0, 0 },
-                      { duration: 100, waveFreq: { 440, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 1 },                              // TONE_ANSI_CALL_WAITING
-        { segments: { { duration: 2000, waveFreq: { 440, 480, 0 }, 0, 0 },
-                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_ANSI_RINGTONE
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 400, 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_JAPAN_DIAL
-        { segments: { { duration: 500, waveFreq: { 400, 0 }, 0, 0 },
-                      { duration: 500, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_JAPAN_BUSY
-        { segments: { { duration: 1000, waveFreq: { 400, 0 }, 0, 0 },
-                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
-                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
-          repeatCnt: ToneGenerator::TONEGEN_INF,
-          repeatSegment: 0 },                              // TONE_JAPAN_RADIO_ACK
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 350, 440, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_ANSI_DIAL
+        { .segments = { { .duration = 500, .waveFreq = { 480, 620, 0 }, 0, 0 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_ANSI_BUSY
+        { .segments = { { .duration = 250, .waveFreq = { 480, 620, 0 }, 0, 0 },
+                        { .duration = 250, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_ANSI_CONGESTION
+        { .segments = { { .duration = 300, .waveFreq = { 440, 0 }, 0, 0 },
+                        { .duration = 9700, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 100, .waveFreq = { 440, 0 }, 0, 0 },
+                        { .duration = 100, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 100, .waveFreq = { 440, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 1 },                              // TONE_ANSI_CALL_WAITING
+        { .segments = { { .duration = 2000, .waveFreq = { 440, 480, 0 }, 0, 0 },
+                        { .duration = 4000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_ANSI_RINGTONE
+        { .segments = { { .duration = ToneGenerator::TONEGEN_INF, .waveFreq = { 400, 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_JAPAN_DIAL
+        { .segments = { { .duration = 500, .waveFreq = { 400, 0 }, 0, 0 },
+                        { .duration = 500, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_JAPAN_BUSY
+        { .segments = { { .duration = 1000, .waveFreq = { 400, 0 }, 0, 0 },
+                        { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+                        { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+          .repeatCnt = ToneGenerator::TONEGEN_INF,
+          .repeatSegment = 0 },                              // TONE_JAPAN_RADIO_ACK
 
 
 
diff --git a/media/libmedia/docs/Makefile b/media/libmedia/docs/Makefile
new file mode 100644
index 0000000..bddbc9b
--- /dev/null
+++ b/media/libmedia/docs/Makefile
@@ -0,0 +1,2 @@
+paused.png : paused.dot
+	dot -Tpng < $< > $@
diff --git a/media/libmedia/docs/paused.dot b/media/libmedia/docs/paused.dot
new file mode 100644
index 0000000..11e1777
--- /dev/null
+++ b/media/libmedia/docs/paused.dot
@@ -0,0 +1,85 @@
+digraph paused {
+initial [label="INITIAL\n\
+mIgnoreNextPausedInt = false\n\
+mPaused = false\n\
+mPausedInt = false"];
+
+resume_body [label="mIgnoreNextPausedInt = true\nif (mPaused || mPausedInt)"];
+resume_paused [label="mPaused = false\nmPausedInt = false\nsignal()"];
+resume_paused -> resume_merged;
+resume_merged [label="return"];
+
+Application -> ATstop;
+ATstop [label="AudioTrack::stop()"];
+ATstop -> pause;
+Application -> ATpause;
+ATpause [label="AudioTrack::pause()"];
+ATpause -> pause;
+ATstart -> resume;
+ATstart [label="AudioTrack::start()"];
+destructor [label="~AudioTrack()"];
+destructor -> requestExit;
+requestExit [label="AudioTrackThread::requestExit()"];
+requestExit -> resume;
+Application -> ATsetMarkerPosition
+ATsetMarkerPosition [label="AudioTrack::setMarkerPosition()\n[sets marker variables]"];
+ATsetMarkerPosition -> ATTwake
+Application -> ATsetPositionUpdatePeriod
+ATsetPositionUpdatePeriod [label="AudioTrack::setPositionUpdatePeriod()\n[sets update period variables]"];
+ATsetPositionUpdatePeriod -> ATTwake
+Application -> ATstart;
+
+resume [label="AudioTrackThread::resume()"];
+resume -> resume_body;
+
+resume_body -> resume_paused [label="true"];
+resume_body -> resume_merged [label="false"];
+
+ATTwake [label="AudioTrackThread::wake()\nif (!mPaused && mPausedInt && mPausedNs > 0)"];
+ATTwake-> ATTWake_wakeable [label="true"];
+ATTWake_wakeable [label="mIgnoreNextPausedInt = true\nmPausedInt = false\nsignal()"];
+ATTwake-> ATTWake_cannotwake [label="false"]
+ATTWake_cannotwake [label="ignore"];
+
+pause [label="mPaused = true"];
+pause -> return;
+
+threadLoop [label="AudioTrackThread::threadLoop()\nENTRY"];
+threadLoop -> threadLoop_1;
+threadLoop_1 [label="if (mPaused)"];
+threadLoop_1 -> threadLoop_1_true [label="true"];
+threadLoop_1 -> threadLoop_2 [label="false"];
+threadLoop_1_true [label="wait()\nreturn true"];
+threadLoop_2 [label="if (mIgnoreNextPausedInt)"];
+threadLoop_2 -> threadLoop_2_true [label="true"];
+threadLoop_2 -> threadLoop_3 [label="false"];
+threadLoop_2_true [label="mIgnoreNextPausedInt = false\nmPausedInt = false"];
+threadLoop_2_true -> threadLoop_3;
+threadLoop_3 [label="if (mPausedInt)"];
+threadLoop_3 -> threadLoop_3_true [label="true"];
+threadLoop_3 -> threadLoop_4 [label="false"];
+threadLoop_3_true [label="wait()\nmPausedInt = false\nreturn true"];
+threadLoop_4 [label="if (exitPending)"];
+threadLoop_4 -> threadLoop_4_true [label="true"];
+threadLoop_4 -> threadLoop_5 [label="false"];
+threadLoop_4_true [label="return false"];
+threadLoop_5 [label="ns = processAudioBuffer()"];
+threadLoop_5 -> threadLoop_6;
+threadLoop_6 [label="case ns"];
+threadLoop_6 -> threadLoop_6_0 [label="0"];
+threadLoop_6 -> threadLoop_6_NS_INACTIVE [label="NS_INACTIVE"];
+threadLoop_6 -> threadLoop_6_NS_NEVER [label="NS_NEVER"];
+threadLoop_6 -> threadLoop_6_NS_WHENEVER [label="NS_WHENEVER"];
+threadLoop_6 -> threadLoop_6_default [label="default"];
+threadLoop_6_default [label="if (ns < 0)"];
+threadLoop_6_default -> threadLoop_6_default_true [label="true"];
+threadLoop_6_default -> threadLoop_6_default_false [label="false"];
+threadLoop_6_default_true [label="FATAL"];
+threadLoop_6_default_false [label="pauseInternal(ns) [wake()-able]\nmPausedInternal = true\nmPausedNs = ns\nreturn true"];
+threadLoop_6_0 [label="return true"];
+threadLoop_6_NS_INACTIVE [label="pauseInternal()\nmPausedInternal = true\nmPausedNs = 0\nreturn true"];
+threadLoop_6_NS_NEVER [label="return false"];
+threadLoop_6_NS_WHENEVER [label="ns = 1s"];
+threadLoop_6_NS_WHENEVER -> threadLoop_6_default_false;
+
+}
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 39a239d..8e8a1ed 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -172,7 +172,7 @@
 {
     Mutex::Autolock lock(sServiceLock);
     if (sService != 0) {
-        sService->asBinder()->unlinkToDeath(this);
+        IInterface::asBinder(sService)->unlinkToDeath(this);
     }
 }
 
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 9611ac7..d1d51cc 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -59,6 +59,7 @@
     mLoop = false;
     mLeftVolume = mRightVolume = 1.0;
     mVideoWidth = mVideoHeight = 0;
+    mPlaybackRate = 1.0;
     mLockThreadId = 0;
     mAudioSessionId = AudioSystem::newAudioUniqueId();
     AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
@@ -240,7 +241,7 @@
 // must call with lock held
 status_t MediaPlayer::prepareAsync_l()
 {
-    if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
+    if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
         mPlayer->setAudioStreamType(mStreamType);
         if (mAudioAttributesParcel != NULL) {
             mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
@@ -378,6 +379,24 @@
     return false;
 }
 
+status_t MediaPlayer::setPlaybackRate(float rate)
+{
+    ALOGV("setPlaybackRate: %f", rate);
+    if (rate <= 0.0) {
+        return BAD_VALUE;
+    }
+    Mutex::Autolock _l(mLock);
+    if (mPlayer != 0) {
+        if (mPlaybackRate == rate) {
+            return NO_ERROR;
+        }
+        mPlaybackRate = rate;
+        return mPlayer->setPlaybackRate(rate);
+    }
+    ALOGV("setPlaybackRate: no active player");
+    return INVALID_OPERATION;
+}
+
 status_t MediaPlayer::getVideoWidth(int *w)
 {
     ALOGV("getVideoWidth");
@@ -414,7 +433,8 @@
 status_t MediaPlayer::getDuration_l(int *msec)
 {
     ALOGV("getDuration_l");
-    bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
+    bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
+            MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
     if (mPlayer != 0 && isValidState) {
         int durationMs;
         status_t ret = mPlayer->getDuration(&durationMs);
@@ -443,7 +463,8 @@
 status_t MediaPlayer::seekTo_l(int msec)
 {
     ALOGV("seekTo %d", msec);
-    if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED |  MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
+    if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
+            MEDIA_PLAYER_PAUSED |  MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
         if ( msec < 0 ) {
             ALOGW("Attempt to seek to invalid position: %d", msec);
             msec = 0;
@@ -477,7 +498,8 @@
             return NO_ERROR;
         }
     }
-    ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
+    ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(),
+            mCurrentState);
     return INVALID_OPERATION;
 }
 
@@ -835,53 +857,12 @@
     }
 }
 
-/*static*/ status_t MediaPlayer::decode(
-        const sp<IMediaHTTPService> &httpService,
-        const char* url,
-        uint32_t *pSampleRate,
-        int* pNumChannels,
-        audio_format_t* pFormat,
-        const sp<IMemoryHeap>& heap,
-        size_t *pSize)
-{
-    ALOGV("decode(%s)", url);
-    status_t status;
-    const sp<IMediaPlayerService>& service = getMediaPlayerService();
-    if (service != 0) {
-        status = service->decode(httpService, url, pSampleRate, pNumChannels, pFormat, heap, pSize);
-    } else {
-        ALOGE("Unable to locate media service");
-        status = DEAD_OBJECT;
-    }
-    return status;
-
-}
-
 void MediaPlayer::died()
 {
     ALOGV("died");
     notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
 }
 
-/*static*/ status_t MediaPlayer::decode(int fd, int64_t offset, int64_t length,
-                                        uint32_t *pSampleRate, int* pNumChannels,
-                                        audio_format_t* pFormat,
-                                        const sp<IMemoryHeap>& heap, size_t *pSize)
-{
-    ALOGV("decode(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
-    status_t status;
-    const sp<IMediaPlayerService>& service = getMediaPlayerService();
-    if (service != 0) {
-        status = service->decode(fd, offset, length, pSampleRate,
-                                 pNumChannels, pFormat, heap, pSize);
-    } else {
-        ALOGE("Unable to locate media service");
-        status = DEAD_OBJECT;
-    }
-    return status;
-
-}
-
 status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
     if (mPlayer == NULL) {
         return NO_INIT;
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 1952b86..973e156 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -264,32 +264,6 @@
     return ret;
 }
 
-status_t MediaRecorder::setOutputFile(const char* path)
-{
-    ALOGV("setOutputFile(%s)", path);
-    if (mMediaRecorder == NULL) {
-        ALOGE("media recorder is not initialized yet");
-        return INVALID_OPERATION;
-    }
-    if (mIsOutputFileSet) {
-        ALOGE("output file has already been set");
-        return INVALID_OPERATION;
-    }
-    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
-        ALOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
-        return INVALID_OPERATION;
-    }
-
-    status_t ret = mMediaRecorder->setOutputFile(path);
-    if (OK != ret) {
-        ALOGV("setOutputFile failed: %d", ret);
-        mCurrentState = MEDIA_RECORDER_ERROR;
-        return ret;
-    }
-    mIsOutputFileSet = true;
-    return ret;
-}
-
 status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length)
 {
     ALOGV("setOutputFile(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 2cf5710..4b31715 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -10,13 +10,12 @@
     ActivityManager.cpp         \
     Crypto.cpp                  \
     Drm.cpp                     \
+    DrmSessionManager.cpp       \
     HDCP.cpp                    \
     MediaPlayerFactory.cpp      \
     MediaPlayerService.cpp      \
     MediaRecorderClient.cpp     \
     MetadataRetrieverClient.cpp \
-    MidiFile.cpp                \
-    MidiMetadataRetriever.cpp   \
     RemoteDisplay.cpp           \
     SharedLibrary.cpp           \
     StagefrightPlayer.cpp       \
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index 2a8b2c6..d4f6fab 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -23,6 +23,8 @@
 
 #include "Drm.h"
 
+#include "DrmSessionClientInterface.h"
+#include "DrmSessionManager.h"
 #include <media/drm/DrmAPI.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AString.h>
@@ -33,6 +35,10 @@
 
 namespace android {
 
+static inline int getCallingPid() {
+    return IPCThreadState::self()->getCallingPid();
+}
+
 static bool checkPermission(const char* permissionString) {
 #ifndef HAVE_ANDROID_OS
     return true;
@@ -57,14 +63,41 @@
     return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0;
 }
 
+struct DrmSessionClient : public DrmSessionClientInterface {
+    DrmSessionClient(Drm* drm) : mDrm(drm) {}
+
+    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
+        sp<Drm> drm = mDrm.promote();
+        if (drm == NULL) {
+            return true;
+        }
+        status_t err = drm->closeSession(sessionId);
+        if (err != OK) {
+            return false;
+        }
+        drm->sendEvent(DrmPlugin::kDrmPluginEventSessionReclaimed, 0, &sessionId, NULL);
+        return true;
+    }
+
+protected:
+    virtual ~DrmSessionClient() {}
+
+private:
+    wp<Drm> mDrm;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
+};
+
 Drm::Drm()
     : mInitCheck(NO_INIT),
+      mDrmSessionClient(new DrmSessionClient(this)),
       mListener(NULL),
       mFactory(NULL),
       mPlugin(NULL) {
 }
 
 Drm::~Drm() {
+    DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
     delete mPlugin;
     mPlugin = NULL;
     closeFactory();
@@ -84,10 +117,10 @@
 {
     Mutex::Autolock lock(mEventLock);
     if (mListener != NULL){
-        mListener->asBinder()->unlinkToDeath(this);
+        IInterface::asBinder(mListener)->unlinkToDeath(this);
     }
     if (listener != NULL) {
-        listener->asBinder()->linkToDeath(this);
+        IInterface::asBinder(listener)->linkToDeath(this);
     }
     mListener = listener;
     return NO_ERROR;
@@ -289,7 +322,18 @@
         return -EINVAL;
     }
 
-    return mPlugin->openSession(sessionId);
+    status_t err = mPlugin->openSession(sessionId);
+    if (err == ERROR_DRM_RESOURCE_BUSY) {
+        bool retry = false;
+        retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
+        if (retry) {
+            err = mPlugin->openSession(sessionId);
+        }
+    }
+    if (err == OK) {
+        DrmSessionManager::Instance()->addSession(getCallingPid(), mDrmSessionClient, sessionId);
+    }
+    return err;
 }
 
 status_t Drm::closeSession(Vector<uint8_t> const &sessionId) {
@@ -303,7 +347,11 @@
         return -EINVAL;
     }
 
-    return mPlugin->closeSession(sessionId);
+    status_t err = mPlugin->closeSession(sessionId);
+    if (err == OK) {
+        DrmSessionManager::Instance()->removeSession(sessionId);
+    }
+    return err;
 }
 
 status_t Drm::getKeyRequest(Vector<uint8_t> const &sessionId,
@@ -321,6 +369,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->getKeyRequest(sessionId, initData, mimeType, keyType,
                                   optionalParameters, request, defaultUrl);
 }
@@ -338,6 +388,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->provideKeyResponse(sessionId, response, keySetId);
 }
 
@@ -367,6 +419,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->restoreKeys(sessionId, keySetId);
 }
 
@@ -382,6 +436,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->queryKeyStatus(sessionId, infoMap);
 }
 
@@ -561,6 +617,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->setCipherAlgorithm(sessionId, algorithm);
 }
 
@@ -576,6 +634,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->setMacAlgorithm(sessionId, algorithm);
 }
 
@@ -594,6 +654,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->encrypt(sessionId, keyId, input, iv, output);
 }
 
@@ -612,6 +674,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->decrypt(sessionId, keyId, input, iv, output);
 }
 
@@ -629,6 +693,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->sign(sessionId, keyId, message, signature);
 }
 
@@ -647,6 +713,8 @@
         return -EINVAL;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->verify(sessionId, keyId, message, signature, match);
 }
 
@@ -669,15 +737,21 @@
         return -EPERM;
     }
 
+    DrmSessionManager::Instance()->useSession(sessionId);
+
     return mPlugin->signRSA(sessionId, algorithm, message, wrappedKey, signature);
 }
 
 void Drm::binderDied(const wp<IBinder> &the_late_who)
 {
+    mEventLock.lock();
+    mListener.clear();
+    mEventLock.unlock();
+
+    Mutex::Autolock autoLock(mLock);
     delete mPlugin;
     mPlugin = NULL;
     closeFactory();
-    mListener.clear();
 }
 
 }  // namespace android
diff --git a/media/libmediaplayerservice/Drm.h b/media/libmediaplayerservice/Drm.h
index 0e1eb2c..0cea639 100644
--- a/media/libmediaplayerservice/Drm.h
+++ b/media/libmediaplayerservice/Drm.h
@@ -28,6 +28,7 @@
 
 struct DrmFactory;
 struct DrmPlugin;
+struct DrmSessionClientInterface;
 
 struct Drm : public BnDrm,
              public IBinder::DeathRecipient,
@@ -138,6 +139,8 @@
 
     status_t mInitCheck;
 
+    sp<DrmSessionClientInterface> mDrmSessionClient;
+
     sp<IDrmClient> mListener;
     mutable Mutex mEventLock;
     mutable Mutex mNotifyLock;
diff --git a/media/libmediaplayerservice/DrmSessionClientInterface.h b/media/libmediaplayerservice/DrmSessionClientInterface.h
new file mode 100644
index 0000000..17faf08
--- /dev/null
+++ b/media/libmediaplayerservice/DrmSessionClientInterface.h
@@ -0,0 +1,34 @@
+/*
+ * 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 DRM_PROXY_INTERFACE_H_
+#define DRM_PROXY_INTERFACE_H_
+
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct DrmSessionClientInterface : public RefBase {
+    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) = 0;
+
+protected:
+    virtual ~DrmSessionClientInterface() {}
+};
+
+}  // namespace android
+
+#endif  // DRM_PROXY_INTERFACE_H_
diff --git a/media/libmediaplayerservice/DrmSessionManager.cpp b/media/libmediaplayerservice/DrmSessionManager.cpp
new file mode 100644
index 0000000..641f881
--- /dev/null
+++ b/media/libmediaplayerservice/DrmSessionManager.cpp
@@ -0,0 +1,240 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "DrmSessionManager"
+#include <utils/Log.h>
+
+#include "DrmSessionManager.h"
+
+#include "DrmSessionClientInterface.h"
+#include <binder/IPCThreadState.h>
+#include <binder/IProcessInfoService.h>
+#include <binder/IServiceManager.h>
+#include <media/stagefright/ProcessInfo.h>
+#include <unistd.h>
+#include <utils/String8.h>
+
+namespace android {
+
+static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) {
+    String8 sessionIdStr;
+    for (size_t i = 0; i < sessionId.size(); ++i) {
+        sessionIdStr.appendFormat("%u ", sessionId[i]);
+    }
+    return sessionIdStr;
+}
+
+bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) {
+    if (sessionId1.size() != sessionId2.size()) {
+        return false;
+    }
+    for (size_t i = 0; i < sessionId1.size(); ++i) {
+        if (sessionId1[i] != sessionId2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+sp<DrmSessionManager> DrmSessionManager::Instance() {
+    static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
+    return drmSessionManager;
+}
+
+DrmSessionManager::DrmSessionManager()
+    : mProcessInfo(new ProcessInfo()),
+      mTime(0) {}
+
+DrmSessionManager::DrmSessionManager(sp<ProcessInfoInterface> processInfo)
+    : mProcessInfo(processInfo),
+      mTime(0) {}
+
+DrmSessionManager::~DrmSessionManager() {}
+
+void DrmSessionManager::addSession(
+        int pid, sp<DrmSessionClientInterface> drm, const Vector<uint8_t> &sessionId) {
+    ALOGV("addSession(pid %d, drm %p, sessionId %s)", pid, drm.get(),
+            GetSessionIdString(sessionId).string());
+
+    Mutex::Autolock lock(mLock);
+    SessionInfo info;
+    info.drm = drm;
+    info.sessionId = sessionId;
+    info.timeStamp = getTime_l();
+    ssize_t index = mSessionMap.indexOfKey(pid);
+    if (index < 0) {
+        // new pid
+        SessionInfos infosForPid;
+        infosForPid.push_back(info);
+        mSessionMap.add(pid, infosForPid);
+    } else {
+        mSessionMap.editValueAt(index).push_back(info);
+    }
+}
+
+void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
+    ALOGV("useSession(%s)", GetSessionIdString(sessionId).string());
+
+    Mutex::Autolock lock(mLock);
+    for (size_t i = 0; i < mSessionMap.size(); ++i) {
+        SessionInfos& infos = mSessionMap.editValueAt(i);
+        for (size_t j = 0; j < infos.size(); ++j) {
+            SessionInfo& info = infos.editItemAt(j);
+            if (isEqualSessionId(sessionId, info.sessionId)) {
+                info.timeStamp = getTime_l();
+                return;
+            }
+        }
+    }
+}
+
+void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
+    ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string());
+
+    Mutex::Autolock lock(mLock);
+    for (size_t i = 0; i < mSessionMap.size(); ++i) {
+        SessionInfos& infos = mSessionMap.editValueAt(i);
+        for (size_t j = 0; j < infos.size(); ++j) {
+            if (isEqualSessionId(sessionId, infos[j].sessionId)) {
+                infos.removeAt(j);
+                return;
+            }
+        }
+    }
+}
+
+void DrmSessionManager::removeDrm(sp<DrmSessionClientInterface> drm) {
+    ALOGV("removeDrm(%p)", drm.get());
+
+    Mutex::Autolock lock(mLock);
+    bool found = false;
+    for (size_t i = 0; i < mSessionMap.size(); ++i) {
+        SessionInfos& infos = mSessionMap.editValueAt(i);
+        for (size_t j = 0; j < infos.size();) {
+            if (infos[j].drm == drm) {
+                ALOGV("removed session (%s)", GetSessionIdString(infos[j].sessionId).string());
+                j = infos.removeAt(j);
+                found = true;
+            } else {
+                ++j;
+            }
+        }
+        if (found) {
+            break;
+        }
+    }
+}
+
+bool DrmSessionManager::reclaimSession(int callingPid) {
+    ALOGV("reclaimSession(%d)", callingPid);
+
+    sp<DrmSessionClientInterface> drm;
+    Vector<uint8_t> sessionId;
+    int lowestPriorityPid;
+    int lowestPriority;
+    {
+        Mutex::Autolock lock(mLock);
+        int callingPriority;
+        if (!mProcessInfo->getPriority(callingPid, &callingPriority)) {
+            return false;
+        }
+        if (!getLowestPriority_l(&lowestPriorityPid, &lowestPriority)) {
+            return false;
+        }
+        if (lowestPriority <= callingPriority) {
+            return false;
+        }
+
+        if (!getLeastUsedSession_l(lowestPriorityPid, &drm, &sessionId)) {
+            return false;
+        }
+    }
+
+    if (drm == NULL) {
+        return false;
+    }
+
+    ALOGV("reclaim session(%s) opened by pid %d",
+            GetSessionIdString(sessionId).string(), lowestPriorityPid);
+
+    return drm->reclaimSession(sessionId);
+}
+
+int64_t DrmSessionManager::getTime_l() {
+    return mTime++;
+}
+
+bool DrmSessionManager::getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority) {
+    int pid = -1;
+    int priority = -1;
+    for (size_t i = 0; i < mSessionMap.size(); ++i) {
+        if (mSessionMap.valueAt(i).size() == 0) {
+            // no opened session by this process.
+            continue;
+        }
+        int tempPid = mSessionMap.keyAt(i);
+        int tempPriority;
+        if (!mProcessInfo->getPriority(tempPid, &tempPriority)) {
+            // shouldn't happen.
+            return false;
+        }
+        if (pid == -1) {
+            pid = tempPid;
+            priority = tempPriority;
+        } else {
+            if (tempPriority > priority) {
+                pid = tempPid;
+                priority = tempPriority;
+            }
+        }
+    }
+    if (pid != -1) {
+        *lowestPriorityPid = pid;
+        *lowestPriority = priority;
+    }
+    return (pid != -1);
+}
+
+bool DrmSessionManager::getLeastUsedSession_l(
+        int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId) {
+    ssize_t index = mSessionMap.indexOfKey(pid);
+    if (index < 0) {
+        return false;
+    }
+
+    int leastUsedIndex = -1;
+    int64_t minTs = LLONG_MAX;
+    const SessionInfos& infos = mSessionMap.valueAt(index);
+    for (size_t j = 0; j < infos.size(); ++j) {
+        if (leastUsedIndex == -1) {
+            leastUsedIndex = j;
+            minTs = infos[j].timeStamp;
+        } else {
+            if (infos[j].timeStamp < minTs) {
+                leastUsedIndex = j;
+                minTs = infos[j].timeStamp;
+            }
+        }
+    }
+    if (leastUsedIndex != -1) {
+        *drm = infos[leastUsedIndex].drm;
+        *sessionId = infos[leastUsedIndex].sessionId;
+    }
+    return (leastUsedIndex != -1);
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/DrmSessionManager.h b/media/libmediaplayerservice/DrmSessionManager.h
new file mode 100644
index 0000000..ba5c268
--- /dev/null
+++ b/media/libmediaplayerservice/DrmSessionManager.h
@@ -0,0 +1,77 @@
+/*
+ * 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 DRM_SESSION_MANAGER_H_
+
+#define DRM_SESSION_MANAGER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+class DrmSessionManagerTest;
+struct DrmSessionClientInterface;
+struct ProcessInfoInterface;
+
+bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2);
+
+struct SessionInfo {
+    sp<DrmSessionClientInterface> drm;
+    Vector<uint8_t> sessionId;
+    int64_t timeStamp;
+};
+
+typedef Vector<SessionInfo > SessionInfos;
+typedef KeyedVector<int, SessionInfos > PidSessionInfosMap;
+
+struct DrmSessionManager : public RefBase {
+    static sp<DrmSessionManager> Instance();
+
+    DrmSessionManager();
+    DrmSessionManager(sp<ProcessInfoInterface> processInfo);
+
+    void addSession(int pid, sp<DrmSessionClientInterface> drm, const Vector<uint8_t>& sessionId);
+    void useSession(const Vector<uint8_t>& sessionId);
+    void removeSession(const Vector<uint8_t>& sessionId);
+    void removeDrm(sp<DrmSessionClientInterface> drm);
+    bool reclaimSession(int callingPid);
+
+protected:
+    virtual ~DrmSessionManager();
+
+private:
+    friend class DrmSessionManagerTest;
+
+    int64_t getTime_l();
+    bool getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority);
+    bool getLeastUsedSession_l(
+            int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId);
+
+    sp<ProcessInfoInterface> mProcessInfo;
+    mutable Mutex mLock;
+    PidSessionInfosMap mSessionMap;
+    int64_t mTime;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DrmSessionManager);
+};
+
+}  // namespace android
+
+#endif  // DRM_SESSION_MANAGER_H_
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index 3e0fc0d..48884b9 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -15,18 +15,21 @@
 ** limitations under the License.
 */
 
+//#define LOG_NDEBUG 0
 #define LOG_TAG "MediaPlayerFactory"
 #include <utils/Log.h>
 
 #include <cutils/properties.h>
 #include <media/IMediaPlayer.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <utils/Errors.h>
 #include <utils/misc.h>
+#include <../libstagefright/include/WVMExtractor.h>
 
 #include "MediaPlayerFactory.h"
 
-#include "MidiFile.h"
 #include "TestPlayerStub.h"
 #include "StagefrightPlayer.h"
 #include "nuplayer/NuPlayerDriver.h"
@@ -179,10 +182,18 @@
     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
                                int fd,
                                int64_t offset,
-                               int64_t /*length*/,
+                               int64_t length,
                                float /*curScore*/) {
-        if (getDefaultPlayerType()
-                == STAGEFRIGHT_PLAYER) {
+        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));
@@ -198,10 +209,28 @@
         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() {
         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 {
@@ -250,75 +279,6 @@
     }
 };
 
-class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
-  public:
-    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
-                               const char* url,
-                               float curScore) {
-        static const float kOurScore = 0.4;
-        static const char* const FILE_EXTS[] = { ".mid",
-                                                 ".midi",
-                                                 ".smf",
-                                                 ".xmf",
-                                                 ".mxmf",
-                                                 ".imy",
-                                                 ".rtttl",
-                                                 ".rtx",
-                                                 ".ota" };
-        if (kOurScore <= curScore)
-            return 0.0;
-
-        // use MidiFile for MIDI extensions
-        int lenURL = strlen(url);
-        for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
-            int len = strlen(FILE_EXTS[i]);
-            int start = lenURL - len;
-            if (start > 0) {
-                if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
-                    return kOurScore;
-                }
-            }
-        }
-
-        return 0.0;
-    }
-
-    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
-                               int fd,
-                               int64_t offset,
-                               int64_t length,
-                               float curScore) {
-        static const float kOurScore = 0.8;
-
-        if (kOurScore <= curScore)
-            return 0.0;
-
-        // Some kind of MIDI?
-        EAS_DATA_HANDLE easdata;
-        if (EAS_Init(&easdata) == EAS_SUCCESS) {
-            EAS_FILE locator;
-            locator.path = NULL;
-            locator.fd = fd;
-            locator.offset = offset;
-            locator.length = length;
-            EAS_HANDLE  eashandle;
-            if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
-                EAS_CloseFile(easdata, eashandle);
-                EAS_Shutdown(easdata);
-                return kOurScore;
-            }
-            EAS_Shutdown(easdata);
-        }
-
-        return 0.0;
-    }
-
-    virtual sp<MediaPlayerBase> createPlayer() {
-        ALOGV(" create MidiFile");
-        return new MidiFile();
-    }
-};
-
 class TestPlayerFactory : public MediaPlayerFactory::IFactory {
   public:
     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
@@ -345,7 +305,6 @@
 
     registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
     registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
-    registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
     registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
 
     sInitComplete = true;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index c120898..f113e21 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -59,6 +59,7 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooperRoster.h>
 
 #include <system/audio.h>
 
@@ -70,7 +71,6 @@
 #include "MetadataRetrieverClient.h"
 #include "MediaPlayerFactory.h"
 
-#include "MidiFile.h"
 #include "TestPlayerStub.h"
 #include "StagefrightPlayer.h"
 #include "nuplayer/NuPlayerDriver.h"
@@ -248,6 +248,9 @@
 
 namespace android {
 
+extern ALooperRoster gLooperRoster;
+
+
 static bool checkPermission(const char* permissionString) {
 #ifndef HAVE_ANDROID_OS
     return true;
@@ -287,8 +290,9 @@
     const sp<IServiceManager> sm(defaultServiceManager());
     if (sm != NULL) {
         const String16 name("batterystats");
+        // use checkService() to avoid blocking if service is not up yet
         sp<IBatteryStats> batteryStats =
-                interface_cast<IBatteryStats>(sm->getService(name));
+                interface_cast<IBatteryStats>(sm->checkService(name));
         if (batteryStats != NULL) {
             batteryStats->noteResetVideo();
             batteryStats->noteResetAudio();
@@ -385,28 +389,6 @@
     return new RemoteDisplay(client, iface.string());
 }
 
-status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& /*args*/) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    result.append(" AudioCache\n");
-    if (mHeap != 0) {
-        snprintf(buffer, 255, "  heap base(%p), size(%zu), flags(%d)\n",
-                mHeap->getBase(), mHeap->getSize(), mHeap->getFlags());
-        result.append(buffer);
-    }
-    snprintf(buffer, 255, "  msec per frame(%f), channel count(%d), format(%d), frame count(%zd)\n",
-            mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
-    result.append(buffer);
-    snprintf(buffer, 255, "  sample rate(%d), size(%d), error(%d), command complete(%s)\n",
-            mSampleRate, mSize, mError, mCommandComplete?"true":"false");
-    result.append(buffer);
-    ::write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
 status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
 {
     const size_t SIZE = 256;
@@ -451,11 +433,18 @@
     return NO_ERROR;
 }
 
+/**
+ * The only arguments this understands right now are -c, -von and -voff,
+ * which are parsed by ALooperRoster::dump()
+ */
 status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
+    SortedVector< sp<Client> > clients; //to serialise the mutex unlock & client destruction.
+    SortedVector< sp<MediaRecorderClient> > mediaRecorderClients;
+
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
         snprintf(buffer, SIZE, "Permission Denial: "
                 "can't dump MediaPlayerService from pid=%d, uid=%d\n",
@@ -467,6 +456,7 @@
         for (int i = 0, n = mClients.size(); i < n; ++i) {
             sp<Client> c = mClients[i].promote();
             if (c != 0) c->dump(fd, args);
+            clients.add(c);
         }
         if (mMediaRecorderClients.size() == 0) {
                 result.append(" No media recorder client\n\n");
@@ -479,12 +469,13 @@
                     write(fd, result.string(), result.size());
                     result = "\n";
                     c->dump(fd, args);
+                    mediaRecorderClients.add(c);
                 }
             }
         }
 
         result.append(" Files opened and/or mapped:\n");
-        snprintf(buffer, SIZE, "/proc/%d/maps", gettid());
+        snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
         FILE *f = fopen(buffer, "r");
         if (f) {
             while (!feof(f)) {
@@ -504,13 +495,13 @@
             result.append("\n");
         }
 
-        snprintf(buffer, SIZE, "/proc/%d/fd", gettid());
+        snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
         DIR *d = opendir(buffer);
         if (d) {
             struct dirent *ent;
             while((ent = readdir(d)) != NULL) {
                 if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
-                    snprintf(buffer, SIZE, "/proc/%d/fd/%s", gettid(), ent->d_name);
+                    snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
                     struct stat s;
                     if (lstat(buffer, &s) == 0) {
                         if ((s.st_mode & S_IFMT) == S_IFLNK) {
@@ -551,6 +542,8 @@
             result.append("\n");
         }
 
+        gLooperRoster.dump(fd, args);
+
         bool dumpMem = false;
         for (size_t i = 0; i < args.size(); i++) {
             if (args[i] == String16("-m")) {
@@ -817,8 +810,7 @@
     sp<MediaPlayerBase> p = getPlayer();
     if (p == 0) return UNKNOWN_ERROR;
 
-    sp<IBinder> binder(bufferProducer == NULL ? NULL :
-            bufferProducer->asBinder());
+    sp<IBinder> binder(IInterface::asBinder(bufferProducer));
     if (mConnectedWindowBinder == binder) {
         return OK;
     }
@@ -975,6 +967,14 @@
     return NO_ERROR;
 }
 
+status_t MediaPlayerService::Client::setPlaybackRate(float rate)
+{
+    ALOGV("[%d] setPlaybackRate(%f)", mConnId, rate);
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+    return p->setPlaybackRate(rate);
+}
+
 status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
 {
     ALOGV("getCurrentPosition");
@@ -1281,129 +1281,6 @@
 }
 #endif
 
-status_t MediaPlayerService::decode(
-        const sp<IMediaHTTPService> &httpService,
-        const char* url,
-        uint32_t *pSampleRate,
-        int* pNumChannels,
-        audio_format_t* pFormat,
-        const sp<IMemoryHeap>& heap,
-        size_t *pSize)
-{
-    ALOGV("decode(%s)", url);
-    sp<MediaPlayerBase> player;
-    status_t status = BAD_VALUE;
-
-    // Protect our precious, precious DRMd ringtones by only allowing
-    // decoding of http, but not filesystem paths or content Uris.
-    // If the application wants to decode those, it should open a
-    // filedescriptor for them and use that.
-    if (url != NULL && strncmp(url, "http://", 7) != 0) {
-        ALOGD("Can't decode %s by path, use filedescriptor instead", url);
-        return BAD_VALUE;
-    }
-
-    player_type playerType =
-        MediaPlayerFactory::getPlayerType(NULL /* client */, url);
-    ALOGV("player type = %d", playerType);
-
-    // create the right type of player
-    sp<AudioCache> cache = new AudioCache(heap);
-    player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
-    if (player == NULL) goto Exit;
-    if (player->hardwareOutput()) goto Exit;
-
-    static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
-
-    // set data source
-    if (player->setDataSource(httpService, url) != NO_ERROR) goto Exit;
-
-    ALOGV("prepare");
-    player->prepareAsync();
-
-    ALOGV("wait for prepare");
-    if (cache->wait() != NO_ERROR) goto Exit;
-
-    ALOGV("start");
-    player->start();
-
-    ALOGV("wait for playback complete");
-    cache->wait();
-    // in case of error, return what was successfully decoded.
-    if (cache->size() == 0) {
-        goto Exit;
-    }
-
-    *pSize = cache->size();
-    *pSampleRate = cache->sampleRate();
-    *pNumChannels = cache->channelCount();
-    *pFormat = cache->format();
-    ALOGV("return size %d sampleRate=%u, channelCount = %d, format = %d",
-          *pSize, *pSampleRate, *pNumChannels, *pFormat);
-    status = NO_ERROR;
-
-Exit:
-    if (player != 0) player->reset();
-    return status;
-}
-
-status_t MediaPlayerService::decode(int fd, int64_t offset, int64_t length,
-                                       uint32_t *pSampleRate, int* pNumChannels,
-                                       audio_format_t* pFormat,
-                                       const sp<IMemoryHeap>& heap, size_t *pSize)
-{
-    ALOGV("decode(%d, %lld, %lld)", fd, offset, length);
-    sp<MediaPlayerBase> player;
-    status_t status = BAD_VALUE;
-
-    player_type playerType = MediaPlayerFactory::getPlayerType(NULL /* client */,
-                                                               fd,
-                                                               offset,
-                                                               length);
-    ALOGV("player type = %d", playerType);
-
-    // create the right type of player
-    sp<AudioCache> cache = new AudioCache(heap);
-    player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
-    if (player == NULL) goto Exit;
-    if (player->hardwareOutput()) goto Exit;
-
-    static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
-
-    // set data source
-    if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;
-
-    ALOGV("prepare");
-    player->prepareAsync();
-
-    ALOGV("wait for prepare");
-    if (cache->wait() != NO_ERROR) goto Exit;
-
-    ALOGV("start");
-    player->start();
-
-    ALOGV("wait for playback complete");
-    cache->wait();
-    // in case of error, return what was successfully decoded.
-    if (cache->size() == 0) {
-        goto Exit;
-    }
-
-    *pSize = cache->size();
-    *pSampleRate = cache->sampleRate();
-    *pNumChannels = cache->channelCount();
-    *pFormat = cache->format();
-    ALOGV("return size %d, sampleRate=%u, channelCount = %d, format = %d",
-          *pSize, *pSampleRate, *pNumChannels, *pFormat);
-    status = NO_ERROR;
-
-Exit:
-    if (player != 0) player->reset();
-    ::close(fd);
-    return status;
-}
-
-
 #undef LOG_TAG
 #define LOG_TAG "AudioSink"
 MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid,
@@ -1801,13 +1678,13 @@
     }
 }
 
-ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
+ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size, bool blocking)
 {
     LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
 
     //ALOGV("write(%p, %u)", buffer, size);
     if (mTrack != 0) {
-        ssize_t ret = mTrack->write(buffer, size);
+        ssize_t ret = mTrack->write(buffer, size, blocking);
         if (ret >= 0) {
             mBytesWritten += ret;
         }
@@ -1953,47 +1830,6 @@
     return mTrack->getSampleRate();
 }
 
-#undef LOG_TAG
-#define LOG_TAG "AudioCache"
-MediaPlayerService::AudioCache::AudioCache(const sp<IMemoryHeap>& heap) :
-    mHeap(heap), mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
-    mFrameSize(1), mError(NO_ERROR),  mCommandComplete(false)
-{
-}
-
-uint32_t MediaPlayerService::AudioCache::latency () const
-{
-    return 0;
-}
-
-float MediaPlayerService::AudioCache::msecsPerFrame() const
-{
-    return mMsecsPerFrame;
-}
-
-status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) const
-{
-    if (position == 0) return BAD_VALUE;
-    *position = mSize / mFrameSize;
-    return NO_ERROR;
-}
-
-status_t MediaPlayerService::AudioCache::getTimestamp(AudioTimestamp &ts) const
-{
-    ts.mPosition = mSize / mFrameSize;
-    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-    ts.mTime.tv_sec = now / 1000000000LL;
-    ts.mTime.tv_nsec = now - (1000000000LL * ts.mTime.tv_sec);
-    return NO_ERROR;
-}
-
-status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const
-{
-    if (written == 0) return BAD_VALUE;
-    *written = mSize / mFrameSize;
-    return NO_ERROR;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 struct CallbackThread : public Thread {
@@ -2061,138 +1897,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-status_t MediaPlayerService::AudioCache::open(
-        uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
-        audio_format_t format, int bufferCount,
-        AudioCallback cb, void *cookie, audio_output_flags_t /*flags*/,
-        const audio_offload_info_t* /*offloadInfo*/)
-{
-    ALOGV("open(%u, %d, 0x%x, %d, %d)", sampleRate, channelCount, channelMask, format, bufferCount);
-    if (mHeap->getHeapID() < 0) {
-        return NO_INIT;
-    }
-
-    mSampleRate = sampleRate;
-    mChannelCount = (uint16_t)channelCount;
-    mFormat = format;
-    mMsecsPerFrame = 1.e3 / (float) sampleRate;
-    mFrameSize =  audio_is_linear_pcm(mFormat)
-            ? mChannelCount * audio_bytes_per_sample(mFormat) : 1;
-    mFrameCount = mHeap->getSize() / mFrameSize;
-
-    if (cb != NULL) {
-        mCallbackThread = new CallbackThread(this, cb, cookie);
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayerService::AudioCache::start() {
-    if (mCallbackThread != NULL) {
-        mCallbackThread->run("AudioCache callback");
-    }
-    return NO_ERROR;
-}
-
-void MediaPlayerService::AudioCache::stop() {
-    if (mCallbackThread != NULL) {
-        mCallbackThread->requestExitAndWait();
-    }
-}
-
-ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
-{
-    ALOGV("write(%p, %u)", buffer, size);
-    if ((buffer == 0) || (size == 0)) return size;
-
-    uint8_t* p = static_cast<uint8_t*>(mHeap->getBase());
-    if (p == NULL) return NO_INIT;
-    p += mSize;
-    ALOGV("memcpy(%p, %p, %u)", p, buffer, size);
-
-    bool overflow = mSize + size > mHeap->getSize();
-    if (overflow) {
-        ALOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
-        size = mHeap->getSize() - mSize;
-    }
-    size -= size % mFrameSize; // consume only integral amounts of frame size
-    memcpy(p, buffer, size);
-    mSize += size;
-
-    if (overflow) {
-        // Signal heap filled here (last frame may be truncated).
-        // After this point, no more data should be written as the
-        // heap is filled and the AudioCache should be effectively
-        // immutable with respect to future writes.
-        //
-        // It is thus safe for another thread to read the AudioCache.
-        mCommandComplete = true;
-        mSignal.signal();
-    }
-    return size;
-}
-
-// call with lock held
-status_t MediaPlayerService::AudioCache::wait()
-{
-    Mutex::Autolock lock(mLock);
-    while (!mCommandComplete) {
-        mSignal.wait(mLock);
-    }
-    mCommandComplete = false;
-
-    if (mError == NO_ERROR) {
-        ALOGV("wait - success");
-    } else {
-        ALOGV("wait - error");
-    }
-    return mError;
-}
-
-void MediaPlayerService::AudioCache::notify(
-        void* cookie, int msg, int ext1, int ext2, const Parcel* /*obj*/)
-{
-    ALOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
-    AudioCache* p = static_cast<AudioCache*>(cookie);
-
-    // ignore buffering messages
-    switch (msg)
-    {
-    case MEDIA_ERROR:
-        ALOGE("Error %d, %d occurred", ext1, ext2);
-        break;
-    case MEDIA_PREPARED:
-        ALOGV("prepared");
-        break;
-    case MEDIA_PLAYBACK_COMPLETE:
-        ALOGV("playback complete");
-        break;
-    default:
-        ALOGV("ignored");
-        return;
-    }
-
-    // wake up thread
-    Mutex::Autolock lock(p->mLock);
-    if (msg == MEDIA_ERROR) {
-        p->mError = ext1;
-    }
-    p->mCommandComplete = true;
-    p->mSignal.signal();
-}
-
-int MediaPlayerService::AudioCache::getSessionId() const
-{
-    return 0;
-}
-
-uint32_t MediaPlayerService::AudioCache::getSampleRate() const
-{
-    if (mMsecsPerFrame == 0) {
-        return 0;
-    }
-    return (uint32_t)(1.e3 / mMsecsPerFrame);
-}
-
 void MediaPlayerService::addBatteryData(uint32_t params)
 {
     Mutex::Autolock lock(mLock);
@@ -2236,7 +1940,7 @@
         return;
     }
 
-    // an sudio stream is started
+    // an audio stream is started
     if (params & kBatteryDataAudioFlingerStart) {
         // record the start time only if currently no other audio
         // is being played
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 3b96e88..4ce4b81 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -77,7 +77,6 @@
         virtual                 ~AudioOutput();
 
         virtual bool            ready() const { return mTrack != 0; }
-        virtual bool            realtime() const { return true; }
         virtual ssize_t         bufferSize() const;
         virtual ssize_t         frameCount() const;
         virtual ssize_t         channelCount() const;
@@ -98,7 +97,7 @@
                 const audio_offload_info_t *offloadInfo = NULL);
 
         virtual status_t        start();
-        virtual ssize_t         write(const void* buffer, size_t size);
+        virtual ssize_t         write(const void* buffer, size_t size, bool blocking = true);
         virtual void            stop();
         virtual void            flush();
         virtual void            pause();
@@ -184,75 +183,6 @@
     }; // AudioOutput
 
 
-    class AudioCache : public MediaPlayerBase::AudioSink
-    {
-    public:
-                                AudioCache(const sp<IMemoryHeap>& heap);
-        virtual                 ~AudioCache() {}
-
-        virtual bool            ready() const { return (mChannelCount > 0) && (mHeap->getHeapID() > 0); }
-        virtual bool            realtime() const { return false; }
-        virtual ssize_t         bufferSize() const { return frameSize() * mFrameCount; }
-        virtual ssize_t         frameCount() const { return mFrameCount; }
-        virtual ssize_t         channelCount() const { return (ssize_t)mChannelCount; }
-        virtual ssize_t         frameSize() const { return (ssize_t)mFrameSize; }
-        virtual uint32_t        latency() const;
-        virtual float           msecsPerFrame() const;
-        virtual status_t        getPosition(uint32_t *position) const;
-        virtual status_t        getTimestamp(AudioTimestamp &ts) const;
-        virtual status_t        getFramesWritten(uint32_t *frameswritten) const;
-        virtual int             getSessionId() const;
-        virtual uint32_t        getSampleRate() const;
-
-        virtual status_t        open(
-                uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
-                audio_format_t format, int bufferCount = 1,
-                AudioCallback cb = NULL, void *cookie = NULL,
-                audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
-                const audio_offload_info_t *offloadInfo = NULL);
-
-        virtual status_t        start();
-        virtual ssize_t         write(const void* buffer, size_t size);
-        virtual void            stop();
-        virtual void            flush() {}
-        virtual void            pause() {}
-        virtual void            close() {}
-                void            setAudioStreamType(audio_stream_type_t streamType __unused) {}
-                // stream type is not used for AudioCache
-        virtual audio_stream_type_t getAudioStreamType() const { return AUDIO_STREAM_DEFAULT; }
-
-                void            setVolume(float left __unused, float right __unused) {}
-        virtual status_t        setPlaybackRatePermille(int32_t ratePermille __unused) { return INVALID_OPERATION; }
-                uint32_t        sampleRate() const { return mSampleRate; }
-                audio_format_t  format() const { return mFormat; }
-                size_t          size() const { return mSize; }
-                status_t        wait();
-
-                sp<IMemoryHeap> getHeap() const { return mHeap; }
-
-        static  void            notify(void* cookie, int msg,
-                                       int ext1, int ext2, const Parcel *obj);
-        virtual status_t        dump(int fd, const Vector<String16>& args) const;
-
-    private:
-                                AudioCache();
-
-        Mutex               mLock;
-        Condition           mSignal;
-        sp<IMemoryHeap>     mHeap;
-        float               mMsecsPerFrame;
-        uint16_t            mChannelCount;
-        audio_format_t      mFormat;
-        ssize_t             mFrameCount;
-        uint32_t            mSampleRate;
-        uint32_t            mSize;
-        size_t              mFrameSize;
-        int                 mError;
-        bool                mCommandComplete;
-
-        sp<Thread>          mCallbackThread;
-    }; // AudioCache
-
 public:
     static  void                instantiate();
 
@@ -263,19 +193,6 @@
 
     virtual sp<IMediaPlayer>    create(const sp<IMediaPlayerClient>& client, int audioSessionId);
 
-    virtual status_t            decode(
-            const sp<IMediaHTTPService> &httpService,
-            const char* url,
-            uint32_t *pSampleRate,
-            int* pNumChannels,
-            audio_format_t* pFormat,
-            const sp<IMemoryHeap>& heap,
-            size_t *pSize);
-
-    virtual status_t            decode(int fd, int64_t offset, int64_t length,
-                                       uint32_t *pSampleRate, int* pNumChannels,
-                                       audio_format_t* pFormat,
-                                       const sp<IMemoryHeap>& heap, size_t *pSize);
     virtual sp<IMediaCodecList> getCodecList() const;
     virtual sp<IOMX>            getOMX();
     virtual sp<ICrypto>         makeCrypto();
@@ -344,6 +261,7 @@
         virtual status_t        stop();
         virtual status_t        pause();
         virtual status_t        isPlaying(bool* state);
+        virtual status_t        setPlaybackRate(float rate);
         virtual status_t        seekTo(int msec);
         virtual status_t        getCurrentPosition(int* msec);
         virtual status_t        getDuration(int* msec);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 194abbb..4d4de9b 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -154,17 +154,6 @@
     return mRecorder->setAudioEncoder((audio_encoder)ae);
 }
 
-status_t MediaRecorderClient::setOutputFile(const char* path)
-{
-    ALOGV("setOutputFile(%s)", path);
-    Mutex::Autolock lock(mLock);
-    if (mRecorder == NULL) {
-        ALOGE("recorder is not initialized");
-        return NO_INIT;
-    }
-    return mRecorder->setOutputFile(path);
-}
-
 status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t length)
 {
     ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index a65ec9f..a444b6c 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -38,7 +38,6 @@
     virtual     status_t   setOutputFormat(int of);
     virtual     status_t   setVideoEncoder(int ve);
     virtual     status_t   setAudioEncoder(int ae);
-    virtual     status_t   setOutputFile(const char* path);
     virtual     status_t   setOutputFile(int fd, int64_t offset,
                                                   int64_t length);
     virtual     status_t   setVideoSize(int width, int height);
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index fa28451..715cc0c 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -35,7 +35,6 @@
 #include <media/MediaMetadataRetrieverInterface.h>
 #include <media/MediaPlayerInterface.h>
 #include <private/media/VideoFrame.h>
-#include "MidiMetadataRetriever.h"
 #include "MetadataRetrieverClient.h"
 #include "StagefrightMetadataRetriever.h"
 #include "MediaPlayerFactory.h"
@@ -90,10 +89,6 @@
             p = new StagefrightMetadataRetriever;
             break;
         }
-        case SONIVOX_PLAYER:
-            ALOGV("create midi metadata retriever");
-            p = new MidiMetadataRetriever();
-            break;
         default:
             // TODO:
             // support for TEST_PLAYER
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
deleted file mode 100644
index 749ef96..0000000
--- a/media/libmediaplayerservice/MidiFile.cpp
+++ /dev/null
@@ -1,560 +0,0 @@
-/* MidiFile.cpp
-**
-** Copyright 2007, 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 "MidiFile"
-#include "utils/Log.h"
-
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <utils/threads.h>
-#include <libsonivox/eas_reverb.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <system/audio.h>
-
-#include "MidiFile.h"
-
-// ----------------------------------------------------------------------------
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-// The midi engine buffers are a bit small (128 frames), so we batch them up
-static const int NUM_BUFFERS = 4;
-
-// TODO: Determine appropriate return codes
-static status_t ERROR_NOT_OPEN = -1;
-static status_t ERROR_OPEN_FAILED = -2;
-static status_t ERROR_EAS_FAILURE = -3;
-static status_t ERROR_ALLOCATE_FAILED = -4;
-
-static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
-
-MidiFile::MidiFile() :
-    mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL),
-    mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR),
-    mStreamType(AUDIO_STREAM_MUSIC), mLoop(false), mExit(false),
-    mPaused(false), mRender(false), mTid(-1)
-{
-    ALOGV("constructor");
-
-    mFileLocator.path = NULL;
-    mFileLocator.fd = -1;
-    mFileLocator.offset = 0;
-    mFileLocator.length = 0;
-
-    // get the library configuration and do sanity check
-    if (pLibConfig == NULL)
-        pLibConfig = EAS_Config();
-    if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
-        ALOGE("EAS library/header mismatch");
-        goto Failed;
-    }
-
-    // initialize EAS library
-    if (EAS_Init(&mEasData) != EAS_SUCCESS) {
-        ALOGE("EAS_Init failed");
-        goto Failed;
-    }
-
-    // select reverb preset and enable
-    EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER);
-    EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE);
-
-    // create playback thread
-    {
-        Mutex::Autolock l(mMutex);
-        mThread = new MidiFileThread(this);
-        mThread->run("midithread", ANDROID_PRIORITY_AUDIO);
-        mCondition.wait(mMutex);
-        ALOGV("thread started");
-    }
-
-    // indicate success
-    if (mTid > 0) {
-        ALOGV(" render thread(%d) started", mTid);
-        mState = EAS_STATE_READY;
-    }
-
-Failed:
-    return;
-}
-
-status_t MidiFile::initCheck()
-{
-    if (mState == EAS_STATE_ERROR) return ERROR_EAS_FAILURE;
-    return NO_ERROR;
-}
-
-MidiFile::~MidiFile() {
-    ALOGV("MidiFile destructor");
-    release();
-}
-
-status_t MidiFile::setDataSource(
-        const sp<IMediaHTTPService> & /*httpService*/,
-        const char* path,
-        const KeyedVector<String8, String8> *) {
-    ALOGV("MidiFile::setDataSource url=%s", path);
-    Mutex::Autolock lock(mMutex);
-
-    // file still open?
-    if (mEasHandle) {
-        reset_nosync();
-    }
-
-    // open file and set paused state
-    mFileLocator.path = strdup(path);
-    mFileLocator.fd = -1;
-    mFileLocator.offset = 0;
-    mFileLocator.length = 0;
-    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
-    if (result == EAS_SUCCESS) {
-        updateState();
-    }
-
-    if (result != EAS_SUCCESS) {
-        ALOGE("EAS_OpenFile failed: [%d]", (int)result);
-        mState = EAS_STATE_ERROR;
-        return ERROR_OPEN_FAILED;
-    }
-
-    mState = EAS_STATE_OPEN;
-    mPlayTime = 0;
-    return NO_ERROR;
-}
-
-status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length)
-{
-    ALOGV("MidiFile::setDataSource fd=%d", fd);
-    Mutex::Autolock lock(mMutex);
-
-    // file still open?
-    if (mEasHandle) {
-        reset_nosync();
-    }
-
-    // open file and set paused state
-    mFileLocator.fd = dup(fd);
-    mFileLocator.offset = offset;
-    mFileLocator.length = length;
-    EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
-    updateState();
-
-    if (result != EAS_SUCCESS) {
-        ALOGE("EAS_OpenFile failed: [%d]", (int)result);
-        mState = EAS_STATE_ERROR;
-        return ERROR_OPEN_FAILED;
-    }
-
-    mState = EAS_STATE_OPEN;
-    mPlayTime = 0;
-    return NO_ERROR;
-}
-
-status_t MidiFile::prepare()
-{
-    ALOGV("MidiFile::prepare");
-    Mutex::Autolock lock(mMutex);
-    if (!mEasHandle) {
-        return ERROR_NOT_OPEN;
-    }
-    EAS_RESULT result;
-    if ((result = EAS_Prepare(mEasData, mEasHandle)) != EAS_SUCCESS) {
-        ALOGE("EAS_Prepare failed: [%ld]", result);
-        return ERROR_EAS_FAILURE;
-    }
-    updateState();
-    return NO_ERROR;
-}
-
-status_t MidiFile::prepareAsync()
-{
-    ALOGV("MidiFile::prepareAsync");
-    status_t ret = prepare();
-
-    // don't hold lock during callback
-    if (ret == NO_ERROR) {
-        sendEvent(MEDIA_PREPARED);
-    } else {
-        sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ret);
-    }
-    return ret;
-}
-
-status_t MidiFile::start()
-{
-    ALOGV("MidiFile::start");
-    Mutex::Autolock lock(mMutex);
-    if (!mEasHandle) {
-        return ERROR_NOT_OPEN;
-    }
-
-    // resuming after pause?
-    if (mPaused) {
-        if (EAS_Resume(mEasData, mEasHandle) != EAS_SUCCESS) {
-            return ERROR_EAS_FAILURE;
-        }
-        mPaused = false;
-        updateState();
-    }
-
-    mRender = true;
-    if (mState == EAS_STATE_PLAY) {
-        sendEvent(MEDIA_STARTED);
-    }
-
-    // wake up render thread
-    ALOGV("  wakeup render thread");
-    mCondition.signal();
-    return NO_ERROR;
-}
-
-status_t MidiFile::stop()
-{
-    ALOGV("MidiFile::stop");
-    Mutex::Autolock lock(mMutex);
-    if (!mEasHandle) {
-        return ERROR_NOT_OPEN;
-    }
-    if (!mPaused && (mState != EAS_STATE_STOPPED)) {
-        EAS_RESULT result = EAS_Pause(mEasData, mEasHandle);
-        if (result != EAS_SUCCESS) {
-            ALOGE("EAS_Pause returned error %ld", result);
-            return ERROR_EAS_FAILURE;
-        }
-    }
-    mPaused = false;
-    sendEvent(MEDIA_STOPPED);
-    return NO_ERROR;
-}
-
-status_t MidiFile::seekTo(int position)
-{
-    ALOGV("MidiFile::seekTo %d", position);
-    // hold lock during EAS calls
-    {
-        Mutex::Autolock lock(mMutex);
-        if (!mEasHandle) {
-            return ERROR_NOT_OPEN;
-        }
-        EAS_RESULT result;
-        if ((result = EAS_Locate(mEasData, mEasHandle, position, false))
-                != EAS_SUCCESS)
-        {
-            ALOGE("EAS_Locate returned %ld", result);
-            return ERROR_EAS_FAILURE;
-        }
-        EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
-    }
-    sendEvent(MEDIA_SEEK_COMPLETE);
-    return NO_ERROR;
-}
-
-status_t MidiFile::pause()
-{
-    ALOGV("MidiFile::pause");
-    Mutex::Autolock lock(mMutex);
-    if (!mEasHandle) {
-        return ERROR_NOT_OPEN;
-    }
-    if ((mState == EAS_STATE_PAUSING) || (mState == EAS_STATE_PAUSED)) return NO_ERROR;
-    if (EAS_Pause(mEasData, mEasHandle) != EAS_SUCCESS) {
-        return ERROR_EAS_FAILURE;
-    }
-    mPaused = true;
-    sendEvent(MEDIA_PAUSED);
-    return NO_ERROR;
-}
-
-bool MidiFile::isPlaying()
-{
-    ALOGV("MidiFile::isPlaying, mState=%d", int(mState));
-    if (!mEasHandle || mPaused) return false;
-    return (mState == EAS_STATE_PLAY);
-}
-
-status_t MidiFile::getCurrentPosition(int* position)
-{
-    ALOGV("MidiFile::getCurrentPosition");
-    if (!mEasHandle) {
-        ALOGE("getCurrentPosition(): file not open");
-        return ERROR_NOT_OPEN;
-    }
-    if (mPlayTime < 0) {
-        ALOGE("getCurrentPosition(): mPlayTime = %ld", mPlayTime);
-        return ERROR_EAS_FAILURE;
-    }
-    *position = mPlayTime;
-    return NO_ERROR;
-}
-
-status_t MidiFile::getDuration(int* duration)
-{
-
-    ALOGV("MidiFile::getDuration");
-    {
-        Mutex::Autolock lock(mMutex);
-        if (!mEasHandle) return ERROR_NOT_OPEN;
-        *duration = mDuration;
-    }
-
-    // if no duration cached, get the duration
-    // don't need a lock here because we spin up a new engine
-    if (*duration < 0) {
-        EAS_I32 temp;
-        EAS_DATA_HANDLE easData = NULL;
-        EAS_HANDLE easHandle = NULL;
-        EAS_RESULT result = EAS_Init(&easData);
-        if (result == EAS_SUCCESS) {
-            result = EAS_OpenFile(easData, &mFileLocator, &easHandle);
-        }
-        if (result == EAS_SUCCESS) {
-            result = EAS_Prepare(easData, easHandle);
-        }
-        if (result == EAS_SUCCESS) {
-            result = EAS_ParseMetaData(easData, easHandle, &temp);
-        }
-        if (easHandle) {
-            EAS_CloseFile(easData, easHandle);
-        }
-        if (easData) {
-            EAS_Shutdown(easData);
-        }
-
-        if (result != EAS_SUCCESS) {
-            return ERROR_EAS_FAILURE;
-        }
-
-        // cache successful result
-        mDuration = *duration = int(temp);
-    }
-
-    return NO_ERROR;
-}
-
-status_t MidiFile::release()
-{
-    ALOGV("MidiFile::release");
-    Mutex::Autolock l(mMutex);
-    reset_nosync();
-
-    // wait for render thread to exit
-    mExit = true;
-    mCondition.signal();
-
-    // wait for thread to exit
-    if (mAudioBuffer) {
-        mCondition.wait(mMutex);
-    }
-
-    // release resources
-    if (mEasData) {
-        EAS_Shutdown(mEasData);
-        mEasData = NULL;
-    }
-    return NO_ERROR;
-}
-
-status_t MidiFile::reset()
-{
-    ALOGV("MidiFile::reset");
-    Mutex::Autolock lock(mMutex);
-    return reset_nosync();
-}
-
-// call only with mutex held
-status_t MidiFile::reset_nosync()
-{
-    ALOGV("MidiFile::reset_nosync");
-    sendEvent(MEDIA_STOPPED);
-    // close file
-    if (mEasHandle) {
-        EAS_CloseFile(mEasData, mEasHandle);
-        mEasHandle = NULL;
-    }
-    if (mFileLocator.path) {
-        free((void*)mFileLocator.path);
-        mFileLocator.path = NULL;
-    }
-    if (mFileLocator.fd >= 0) {
-        close(mFileLocator.fd);
-    }
-    mFileLocator.fd = -1;
-    mFileLocator.offset = 0;
-    mFileLocator.length = 0;
-
-    mPlayTime = -1;
-    mDuration = -1;
-    mLoop = false;
-    mPaused = false;
-    mRender = false;
-    return NO_ERROR;
-}
-
-status_t MidiFile::setLooping(int loop)
-{
-    ALOGV("MidiFile::setLooping");
-    Mutex::Autolock lock(mMutex);
-    if (!mEasHandle) {
-        return ERROR_NOT_OPEN;
-    }
-    loop = loop ? -1 : 0;
-    if (EAS_SetRepeat(mEasData, mEasHandle, loop) != EAS_SUCCESS) {
-        return ERROR_EAS_FAILURE;
-    }
-    return NO_ERROR;
-}
-
-status_t MidiFile::createOutputTrack() {
-    if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels,
-            CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT, 2 /*bufferCount*/) != NO_ERROR) {
-        ALOGE("mAudioSink open failed");
-        return ERROR_OPEN_FAILED;
-    }
-    return NO_ERROR;
-}
-
-int MidiFile::render() {
-    EAS_RESULT result = EAS_FAILURE;
-    EAS_I32 count;
-    int temp;
-    bool audioStarted = false;
-
-    ALOGV("MidiFile::render");
-
-    // allocate render buffer
-    mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS];
-    if (!mAudioBuffer) {
-        ALOGE("mAudioBuffer allocate failed");
-        goto threadExit;
-    }
-
-    // signal main thread that we started
-    {
-        Mutex::Autolock l(mMutex);
-        mTid = gettid();
-        ALOGV("render thread(%d) signal", mTid);
-        mCondition.signal();
-    }
-
-    while (1) {
-        mMutex.lock();
-
-        // nothing to render, wait for client thread to wake us up
-        while (!mRender && !mExit)
-        {
-            ALOGV("MidiFile::render - signal wait");
-            mCondition.wait(mMutex);
-            ALOGV("MidiFile::render - signal rx'd");
-        }
-        if (mExit) {
-            mMutex.unlock();
-            break;
-        }
-
-        // render midi data into the input buffer
-        //ALOGV("MidiFile::render - rendering audio");
-        int num_output = 0;
-        EAS_PCM* p = mAudioBuffer;
-        for (int i = 0; i < NUM_BUFFERS; i++) {
-            result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
-            if (result != EAS_SUCCESS) {
-                ALOGE("EAS_Render returned %ld", result);
-            }
-            p += count * pLibConfig->numChannels;
-            num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
-        }
-
-        // update playback state and position
-        // ALOGV("MidiFile::render - updating state");
-        EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
-        EAS_State(mEasData, mEasHandle, &mState);
-        mMutex.unlock();
-
-        // create audio output track if necessary
-        if (!mAudioSink->ready()) {
-            ALOGV("MidiFile::render - create output track");
-            if (createOutputTrack() != NO_ERROR)
-                goto threadExit;
-        }
-
-        // Write data to the audio hardware
-        // ALOGV("MidiFile::render - writing to audio output");
-        if ((temp = mAudioSink->write(mAudioBuffer, num_output)) < 0) {
-            ALOGE("Error in writing:%d",temp);
-            return temp;
-        }
-
-        // start audio output if necessary
-        if (!audioStarted) {
-            //ALOGV("MidiFile::render - starting audio");
-            mAudioSink->start();
-            audioStarted = true;
-        }
-
-        // still playing?
-        if ((mState == EAS_STATE_STOPPED) || (mState == EAS_STATE_ERROR) ||
-                (mState == EAS_STATE_PAUSED))
-        {
-            switch(mState) {
-            case EAS_STATE_STOPPED:
-            {
-                ALOGV("MidiFile::render - stopped");
-                sendEvent(MEDIA_PLAYBACK_COMPLETE);
-                break;
-            }
-            case EAS_STATE_ERROR:
-            {
-                ALOGE("MidiFile::render - error");
-                sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN);
-                break;
-            }
-            case EAS_STATE_PAUSED:
-                ALOGV("MidiFile::render - paused");
-                break;
-            default:
-                break;
-            }
-            mAudioSink->stop();
-            audioStarted = false;
-            mRender = false;
-        }
-    }
-
-threadExit:
-    mAudioSink.clear();
-    if (mAudioBuffer) {
-        delete [] mAudioBuffer;
-        mAudioBuffer = NULL;
-    }
-    mMutex.lock();
-    mTid = -1;
-    mCondition.signal();
-    mMutex.unlock();
-    return result;
-}
-
-} // end namespace android
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
deleted file mode 100644
index 82e4e88..0000000
--- a/media/libmediaplayerservice/MidiFile.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-**
-** Copyright 2008, 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_MIDIFILE_H
-#define ANDROID_MIDIFILE_H
-
-#include <media/MediaPlayerInterface.h>
-#include <libsonivox/eas.h>
-
-namespace android {
-
-// Note that the name MidiFile is misleading; this actually represents a MIDI file player
-class MidiFile : public MediaPlayerInterface {
-public:
-                        MidiFile();
-                        ~MidiFile();
-
-    virtual status_t    initCheck();
-
-    virtual status_t    setDataSource(
-            const sp<IMediaHTTPService> &httpService,
-            const char* path,
-            const KeyedVector<String8, String8> *headers);
-
-    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t    setVideoSurfaceTexture(
-                                const sp<IGraphicBufferProducer>& /*bufferProducer*/)
-                            { return UNKNOWN_ERROR; }
-    virtual status_t    prepare();
-    virtual status_t    prepareAsync();
-    virtual status_t    start();
-    virtual status_t    stop();
-    virtual status_t    seekTo(int msec);
-    virtual status_t    pause();
-    virtual bool        isPlaying();
-    virtual status_t    getCurrentPosition(int* msec);
-    virtual status_t    getDuration(int* msec);
-    virtual status_t    release();
-    virtual status_t    reset();
-    virtual status_t    setLooping(int loop);
-    virtual player_type playerType() { return SONIVOX_PLAYER; }
-    virtual status_t    invoke(const Parcel& /*request*/, Parcel* /*reply*/) {
-        return INVALID_OPERATION;
-    }
-    virtual status_t    setParameter(int /*key*/, const Parcel &/*request*/) {
-        return INVALID_OPERATION;
-    }
-    virtual status_t    getParameter(int /*key*/, Parcel* /*reply*/) {
-        return INVALID_OPERATION;
-    }
-
-
-private:
-            status_t    createOutputTrack();
-            status_t    reset_nosync();
-            int         render();
-            void        updateState(){ EAS_State(mEasData, mEasHandle, &mState); }
-
-    Mutex               mMutex;
-    Condition           mCondition;
-    EAS_DATA_HANDLE     mEasData;
-    EAS_HANDLE          mEasHandle;
-    EAS_PCM*            mAudioBuffer;
-    EAS_I32             mPlayTime;
-    EAS_I32             mDuration;
-    EAS_STATE           mState;
-    EAS_FILE            mFileLocator;
-    audio_stream_type_t mStreamType;
-    bool                mLoop;
-    volatile bool       mExit;
-    bool                mPaused;
-    volatile bool       mRender;
-    pid_t               mTid;
-
-    class MidiFileThread : public Thread {
-    public:
-        MidiFileThread(MidiFile *midiPlayer) : mMidiFile(midiPlayer) {
-        }
-
-    protected:
-        virtual ~MidiFileThread() {}
-
-    private:
-        MidiFile *mMidiFile;
-
-        bool threadLoop() {
-            int result;
-            result = mMidiFile->render();
-            return false;
-        }
-
-        MidiFileThread(const MidiFileThread &);
-        MidiFileThread &operator=(const MidiFileThread &);
-    };
-
-    sp<MidiFileThread> mThread;
-};
-
-}; // namespace android
-
-#endif // ANDROID_MIDIFILE_H
diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.cpp b/media/libmediaplayerservice/MidiMetadataRetriever.cpp
deleted file mode 100644
index f3cf6ef..0000000
--- a/media/libmediaplayerservice/MidiMetadataRetriever.cpp
+++ /dev/null
@@ -1,96 +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.
-*/
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MidiMetadataRetriever"
-#include <utils/Log.h>
-
-#include "MidiMetadataRetriever.h"
-#include <media/mediametadataretriever.h>
-
-#include <media/IMediaHTTPService.h>
-
-namespace android {
-
-static status_t ERROR_NOT_OPEN = -1;
-static status_t ERROR_OPEN_FAILED = -2;
-static status_t ERROR_EAS_FAILURE = -3;
-static status_t ERROR_ALLOCATE_FAILED = -4;
-
-void MidiMetadataRetriever::clearMetadataValues()
-{
-    ALOGV("clearMetadataValues");
-    mMetadataValues[0][0] = '\0';
-}
-
-status_t MidiMetadataRetriever::setDataSource(
-        const sp<IMediaHTTPService> &httpService,
-        const char *url,
-        const KeyedVector<String8, String8> *headers)
-{
-    ALOGV("setDataSource: %s", url? url: "NULL pointer");
-    Mutex::Autolock lock(mLock);
-    clearMetadataValues();
-    if (mMidiPlayer == 0) {
-        mMidiPlayer = new MidiFile();
-    }
-    return mMidiPlayer->setDataSource(httpService, url, headers);
-}
-
-status_t MidiMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
-{
-    ALOGV("setDataSource: fd(%d), offset(%lld), and length(%lld)", fd, offset, length);
-    Mutex::Autolock lock(mLock);
-    clearMetadataValues();
-    if (mMidiPlayer == 0) {
-        mMidiPlayer = new MidiFile();
-    }
-    return mMidiPlayer->setDataSource(fd, offset, length);;
-}
-
-const char* MidiMetadataRetriever::extractMetadata(int keyCode)
-{
-    ALOGV("extractMetdata: key(%d)", keyCode);
-    Mutex::Autolock lock(mLock);
-    if (mMidiPlayer == 0 || mMidiPlayer->initCheck() != NO_ERROR) {
-        ALOGE("Midi player is not initialized yet");
-        return NULL;
-    }
-    switch (keyCode) {
-    case METADATA_KEY_DURATION:
-        {
-            if (mMetadataValues[0][0] == '\0') {
-                int duration = -1;
-                if (mMidiPlayer->getDuration(&duration) != NO_ERROR) {
-                    ALOGE("failed to get duration");
-                    return NULL;
-                }
-                snprintf(mMetadataValues[0], MAX_METADATA_STRING_LENGTH, "%d", duration);
-            }
-
-            ALOGV("duration: %s ms", mMetadataValues[0]);
-            return mMetadataValues[0];
-        }
-    default:
-        ALOGE("Unsupported key code (%d)", keyCode);
-        return NULL;
-    }
-    return NULL;
-}
-
-};
-
diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.h b/media/libmediaplayerservice/MidiMetadataRetriever.h
deleted file mode 100644
index b8214ee..0000000
--- a/media/libmediaplayerservice/MidiMetadataRetriever.h
+++ /dev/null
@@ -1,53 +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_MIDIMETADATARETRIEVER_H
-#define ANDROID_MIDIMETADATARETRIEVER_H
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-#include <media/MediaMetadataRetrieverInterface.h>
-
-#include "MidiFile.h"
-
-namespace android {
-
-class MidiMetadataRetriever : public MediaMetadataRetrieverInterface {
-public:
-                                   MidiMetadataRetriever() {}
-                                   ~MidiMetadataRetriever() {}
-
-    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 const char*             extractMetadata(int keyCode);
-
-private:
-    static const uint32_t MAX_METADATA_STRING_LENGTH = 128;
-    void clearMetadataValues();
-
-    Mutex               mLock;
-    sp<MidiFile>        mMidiPlayer;
-    char                mMetadataValues[1][MAX_METADATA_STRING_LENGTH];
-};
-
-}; // namespace android
-
-#endif // ANDROID_MIDIMETADATARETRIEVER_H
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 3d093fa..55763f0 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -75,6 +75,7 @@
       mAudioSource(AUDIO_SOURCE_CNT),
       mVideoSource(VIDEO_SOURCE_LIST_END),
       mCaptureTimeLapse(false),
+      mCaptureFps(0.0f),
       mStarted(false) {
 
     ALOGV("Constructor");
@@ -206,7 +207,7 @@
 status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
     ALOGV("setVideoFrameRate: %d", frames_per_second);
     if ((frames_per_second <= 0 && frames_per_second != -1) ||
-        frames_per_second > 120) {
+        frames_per_second > kMaxHighSpeedFps) {
         ALOGE("Invalid video frame rate: %d", frames_per_second);
         return BAD_VALUE;
     }
@@ -241,14 +242,6 @@
     return OK;
 }
 
-status_t StagefrightRecorder::setOutputFile(const char * /* path */) {
-    ALOGE("setOutputFile(const char*) must not be called");
-    // We don't actually support this at all, as the media_server process
-    // no longer has permissions to create files.
-
-    return -EPERM;
-}
-
 status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
     ALOGV("setOutputFile: %d, %lld, %lld", fd, offset, length);
     // These don't make any sense, do they?
@@ -260,6 +253,9 @@
         return -EBADF;
     }
 
+    // start with a clean, empty file
+    ftruncate(fd, 0);
+
     if (mOutputFd >= 0) {
         ::close(mOutputFd);
     }
@@ -268,6 +264,31 @@
     return OK;
 }
 
+// Attempt to parse an float literal optionally surrounded by whitespace,
+// returns true on success, false otherwise.
+static bool safe_strtof(const char *s, float *val) {
+    char *end;
+
+    // It is lame, but according to man page, we have to set errno to 0
+    // before calling strtof().
+    errno = 0;
+    *val = strtof(s, &end);
+
+    if (end == s || errno == ERANGE) {
+        return false;
+    }
+
+    // Skip trailing whitespace
+    while (isspace(*end)) {
+        ++end;
+    }
+
+    // For a successful return, the string must contain nothing but a valid
+    // float literal optionally surrounded by whitespace.
+
+    return *end == '\0';
+}
+
 // Attempt to parse an int64 literal optionally surrounded by whitespace,
 // returns true on success, false otherwise.
 static bool safe_strtoi64(const char *s, int64_t *val) {
@@ -551,8 +572,10 @@
     return OK;
 }
 
-status_t StagefrightRecorder::setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs) {
-    ALOGV("setParamTimeBetweenTimeLapseFrameCapture: %lld us", timeUs);
+status_t StagefrightRecorder::setParamTimeLapseFps(float fps) {
+    ALOGV("setParamTimeLapseFps: %.2f", fps);
+
+    int64_t timeUs = (int64_t) (1000000.0 / fps + 0.5f);
 
     // Not allowing time more than a day
     if (timeUs <= 0 || timeUs > 86400*1E6) {
@@ -560,6 +583,7 @@
         return BAD_VALUE;
     }
 
+    mCaptureFps = fps;
     mTimeBetweenTimeLapseFrameCaptureUs = timeUs;
     return OK;
 }
@@ -687,11 +711,10 @@
         if (safe_strtoi32(value.string(), &timeLapseEnable)) {
             return setParamTimeLapseEnable(timeLapseEnable);
         }
-    } else if (key == "time-between-time-lapse-frame-capture") {
-        int64_t timeBetweenTimeLapseFrameCaptureUs;
-        if (safe_strtoi64(value.string(), &timeBetweenTimeLapseFrameCaptureUs)) {
-            return setParamTimeBetweenTimeLapseFrameCapture(
-                    timeBetweenTimeLapseFrameCaptureUs);
+    } else if (key == "time-lapse-fps") {
+        float fps;
+        if (safe_strtof(value.string(), &fps)) {
+            return setParamTimeLapseFps(fps);
         }
     } else {
         ALOGE("setParameter: failed to find key %s", key.string());
@@ -1586,10 +1609,11 @@
 
     status_t err = OK;
     sp<MediaWriter> writer;
+    sp<MPEG4Writer> mp4writer;
     if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
         writer = new WebmWriter(mOutputFd);
     } else {
-        writer = new MPEG4Writer(mOutputFd);
+        writer = mp4writer = new MPEG4Writer(mOutputFd);
     }
 
     if (mVideoSource < VIDEO_SOURCE_LIST_END) {
@@ -1622,13 +1646,15 @@
             mTotalBitRate += mAudioBitRate;
         }
 
+        if (mCaptureTimeLapse) {
+            mp4writer->setCaptureRate(mCaptureFps);
+        }
+
         if (mInterleaveDurationUs > 0) {
-            reinterpret_cast<MPEG4Writer *>(writer.get())->
-                setInterleaveDuration(mInterleaveDurationUs);
+            mp4writer->setInterleaveDuration(mInterleaveDurationUs);
         }
         if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) {
-            reinterpret_cast<MPEG4Writer *>(writer.get())->
-                setGeoData(mLatitudex10000, mLongitudex10000);
+            mp4writer->setGeoData(mLatitudex10000, mLongitudex10000);
         }
     }
     if (mMaxFileDurationUs != 0) {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 54c38d3..f34c229 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -53,7 +53,6 @@
     virtual status_t setVideoFrameRate(int frames_per_second);
     virtual status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
     virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
-    virtual status_t setOutputFile(const char *path);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8& params);
     virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
@@ -110,6 +109,7 @@
     int32_t mTotalBitRate;
 
     bool mCaptureTimeLapse;
+    float mCaptureFps;
     int64_t mTimeBetweenTimeLapseFrameCaptureUs;
     sp<CameraSourceTimeLapse> mCameraSourceTimeLapse;
 
@@ -127,6 +127,8 @@
     sp<IGraphicBufferProducer> mGraphicBufferProducer;
     sp<ALooper> mLooper;
 
+    static const int kMaxHighSpeedFps = 1000;
+
     status_t prepareInternal();
     status_t setupMPEG4orWEBMRecording();
     void setupMPEG4orWEBMMetaData(sp<MetaData> *meta);
@@ -154,7 +156,7 @@
     status_t setParamAudioSamplingRate(int32_t sampleRate);
     status_t setParamAudioTimeScale(int32_t timeScale);
     status_t setParamTimeLapseEnable(int32_t timeLapseEnable);
-    status_t setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs);
+    status_t setParamTimeLapseFps(float fps);
     status_t setParamVideoEncodingBitRate(int32_t bitRate);
     status_t setParamVideoIFramesInterval(int32_t seconds);
     status_t setParamVideoEncoderProfile(int32_t profile);
diff --git a/media/libmediaplayerservice/TestPlayerStub.cpp b/media/libmediaplayerservice/TestPlayerStub.cpp
index 5795773..c8bf6c5 100644
--- a/media/libmediaplayerservice/TestPlayerStub.cpp
+++ b/media/libmediaplayerservice/TestPlayerStub.cpp
@@ -45,7 +45,7 @@
 {
     char prop[PROPERTY_VALUE_MAX] = { '\0', };
 
-    property_get(kBuildTypePropName, prop, '\0');
+    property_get(kBuildTypePropName, prop, "\0");
     return strcmp(prop, kEngBuild) == 0 || strcmp(prop, kTestBuild) == 0;
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index 676c0a6..6609874 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -5,7 +5,9 @@
         GenericSource.cpp               \
         HTTPLiveSource.cpp              \
         NuPlayer.cpp                    \
+        NuPlayerCCDecoder.cpp           \
         NuPlayerDecoder.cpp             \
+        NuPlayerDecoderBase.cpp         \
         NuPlayerDecoderPassThrough.cpp  \
         NuPlayerDriver.cpp              \
         NuPlayerRenderer.cpp            \
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 0e520a8..a040343 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -40,35 +40,50 @@
 
 namespace android {
 
+static int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
+static int64_t kHighWaterMarkUs = 5000000ll;  // 5secs
+static const ssize_t kLowWaterMarkBytes = 40000;
+static const ssize_t kHighWaterMarkBytes = 200000;
+
 NuPlayer::GenericSource::GenericSource(
         const sp<AMessage> &notify,
         bool uidValid,
         uid_t uid)
     : Source(notify),
+      mAudioTimeUs(0),
+      mAudioLastDequeueTimeUs(0),
+      mVideoTimeUs(0),
+      mVideoLastDequeueTimeUs(0),
       mFetchSubtitleDataGeneration(0),
       mFetchTimedTextDataGeneration(0),
       mDurationUs(0ll),
       mAudioIsVorbis(false),
       mIsWidevine(false),
+      mIsSecure(false),
+      mIsStreaming(false),
       mUIDValid(uidValid),
       mUID(uid),
+      mFd(-1),
       mDrmManagerClient(NULL),
-      mMetaDataSize(-1ll),
       mBitrate(-1ll),
       mPollBufferingGeneration(0),
-      mPendingReadBufferTypes(0) {
+      mPendingReadBufferTypes(0),
+      mBuffering(false),
+      mPrepareBuffering(false),
+      mPrevBufferPercentage(-1) {
     resetDataSource();
     DataSource::RegisterDefaultSniffers();
 }
 
 void NuPlayer::GenericSource::resetDataSource() {
-    mAudioTimeUs = 0;
-    mVideoTimeUs = 0;
     mHTTPService.clear();
     mHttpSource.clear();
     mUri.clear();
     mUriHeaders.clear();
-    mFd = -1;
+    if (mFd >= 0) {
+        close(mFd);
+        mFd = -1;
+    }
     mOffset = 0;
     mLength = 0;
     setDrmPlaybackStatusIfNeeded(Playback::STOP, 0);
@@ -115,23 +130,34 @@
 
 status_t NuPlayer::GenericSource::initFromDataSource() {
     sp<MediaExtractor> extractor;
+    String8 mimeType;
+    float confidence;
+    sp<AMessage> dummy;
+    bool isWidevineStreaming = false;
 
     CHECK(mDataSource != NULL);
 
     if (mIsWidevine) {
-        String8 mimeType;
-        float confidence;
-        sp<AMessage> dummy;
-        bool success;
-
-        success = SniffWVM(mDataSource, &mimeType, &confidence, &dummy);
-        if (!success
-                || strcasecmp(
+        isWidevineStreaming = SniffWVM(
+                mDataSource, &mimeType, &confidence, &dummy);
+        if (!isWidevineStreaming ||
+                strcasecmp(
                     mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
             ALOGE("unsupported widevine mime: %s", mimeType.string());
             return UNKNOWN_ERROR;
         }
+    } else if (mIsStreaming) {
+        if (!mDataSource->sniff(&mimeType, &confidence, &dummy)) {
+            return UNKNOWN_ERROR;
+        }
+        isWidevineStreaming = !strcasecmp(
+                mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM);
+    }
 
+    if (isWidevineStreaming) {
+        // we don't want cached source for widevine streaming.
+        mCachedSource.clear();
+        mDataSource = mHttpSource;
         mWVMExtractor = new WVMExtractor(mDataSource);
         mWVMExtractor->setAdaptiveStreamingMode(true);
         if (mUIDValid) {
@@ -140,7 +166,7 @@
         extractor = mWVMExtractor;
     } else {
         extractor = MediaExtractor::Create(mDataSource,
-                mSniffedMIME.empty() ? NULL: mSniffedMIME.c_str());
+                mimeType.isEmpty() ? NULL : mimeType.string());
     }
 
     if (extractor == NULL) {
@@ -157,6 +183,17 @@
         if (mFileMeta->findInt64(kKeyDuration, &duration)) {
             mDurationUs = duration;
         }
+
+        if (!mIsWidevine) {
+            // Check mime to see if we actually have a widevine source.
+            // If the data source is not URL-type (eg. file source), we
+            // won't be able to tell until now.
+            const char *fileMime;
+            if (mFileMeta->findCString(kKeyMIMEType, &fileMime)
+                    && !strncasecmp(fileMime, "video/wvm", 9)) {
+                mIsWidevine = true;
+            }
+        }
     }
 
     int32_t totalBitrate = 0;
@@ -202,7 +239,7 @@
                 int32_t secure;
                 if (meta->findInt32(kKeyRequiresSecureBuffers, &secure)
                         && secure) {
-                    mIsWidevine = true;
+                    mIsSecure = true;
                     if (mUIDValid) {
                         extractor->setUID(mUID);
                     }
@@ -228,6 +265,20 @@
         }
     }
 
+    // Start the selected A/V tracks now before we start buffering.
+    // Widevine sources might re-initialize crypto when starting, if we delay
+    // this to start(), all data buffered during prepare would be wasted.
+    // (We don't actually start reading until start().)
+    if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
+        ALOGE("failed to start audio track!");
+        return UNKNOWN_ERROR;
+    }
+
+    if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
+        ALOGE("failed to start video track!");
+        return UNKNOWN_ERROR;
+    }
+
     mBitrate = totalBitrate;
 
     return OK;
@@ -257,7 +308,7 @@
 
 status_t NuPlayer::GenericSource::setBuffers(
         bool audio, Vector<MediaBuffer *> &buffers) {
-    if (mIsWidevine && !audio) {
+    if (mIsSecure && !audio) {
         return mVideoTrack.mSource->setBuffers(buffers);
     }
     return INVALID_OPERATION;
@@ -268,6 +319,7 @@
         mLooper->unregisterHandler(id());
         mLooper->stop();
     }
+    resetDataSource();
 }
 
 void NuPlayer::GenericSource::prepareAsync() {
@@ -279,15 +331,20 @@
         mLooper->registerHandler(this);
     }
 
-    sp<AMessage> msg = new AMessage(kWhatPrepareAsync, id());
+    sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
     msg->post();
 }
 
 void NuPlayer::GenericSource::onPrepareAsync() {
     // delayed data source creation
     if (mDataSource == NULL) {
+        // set to false first, if the extractor
+        // comes back as secure, set it to true then.
+        mIsSecure = false;
+
         if (!mUri.empty()) {
             const char* uri = mUri.c_str();
+            String8 contentType;
             mIsWidevine = !strncasecmp(uri, "widevine://", 11);
 
             if (!strncasecmp("http://", uri, 7)
@@ -302,14 +359,13 @@
             }
 
             mDataSource = DataSource::CreateFromURI(
-                   mHTTPService, uri, &mUriHeaders, &mContentType,
+                   mHTTPService, uri, &mUriHeaders, &contentType,
                    static_cast<HTTPBase *>(mHttpSource.get()));
         } else {
-            // set to false first, if the extractor
-            // comes back as secure, set it to true then.
             mIsWidevine = false;
 
             mDataSource = new FileSource(mFd, mOffset, mLength);
+            mFd = -1;
         }
 
         if (mDataSource == NULL) {
@@ -322,25 +378,17 @@
             mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
         }
 
-        if (mIsWidevine || mCachedSource != NULL) {
-            schedulePollBuffering();
-        }
+        // For widevine or other cached streaming cases, we need to wait for
+        // enough buffering before reporting prepared.
+        // Note that even when URL doesn't start with widevine://, mIsWidevine
+        // could still be set to true later, if the streaming or file source
+        // is sniffed to be widevine. We don't want to buffer for file source
+        // in that case, so must check the flag now.
+        mIsStreaming = (mIsWidevine || mCachedSource != NULL);
     }
 
-    // check initial caching status
-    status_t err = prefillCacheIfNecessary();
-    if (err != OK) {
-        if (err == -EAGAIN) {
-            (new AMessage(kWhatPrepareAsync, id()))->post(200000);
-        } else {
-            ALOGE("Failed to prefill data cache!");
-            notifyPreparedAndCleanup(UNKNOWN_ERROR);
-        }
-        return;
-    }
-
-    // init extrator from data source
-    err = initFromDataSource();
+    // init extractor from data source
+    status_t err = initFromDataSource();
 
     if (err != OK) {
         ALOGE("Failed to init from data source!");
@@ -360,20 +408,25 @@
     }
 
     notifyFlagsChanged(
-            (mIsWidevine ? FLAG_SECURE : 0)
+            (mIsSecure ? FLAG_SECURE : 0)
+            | (mDecryptHandle != NULL ? FLAG_PROTECTED : 0)
             | FLAG_CAN_PAUSE
             | FLAG_CAN_SEEK_BACKWARD
             | FLAG_CAN_SEEK_FORWARD
             | FLAG_CAN_SEEK);
 
-    notifyPrepared();
+    if (mIsStreaming) {
+        mPrepareBuffering = true;
+
+        ensureCacheIsFetching();
+        restartPollBuffering();
+    } else {
+        notifyPrepared();
+    }
 }
 
 void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
     if (err != OK) {
-        mMetaDataSize = -1ll;
-        mContentType = "";
-        mSniffedMIME = "";
         mDataSource.clear();
         mCachedSource.clear();
         mHttpSource.clear();
@@ -383,103 +436,31 @@
     notifyPrepared(err);
 }
 
-status_t NuPlayer::GenericSource::prefillCacheIfNecessary() {
-    CHECK(mDataSource != NULL);
-
-    if (mCachedSource == NULL) {
-        // no prefill if the data source is not cached
-        return OK;
-    }
-
-    // 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.
-    if (!strncasecmp(mContentType.string(), "audio/", 6)) {
-        return OK;
-    }
-
-    // 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.
-
-    // Initially make sure we have at least 192 KB for the sniff
-    // to complete without blocking.
-    static const size_t kMinBytesForSniffing = 192 * 1024;
-    static const size_t kDefaultMetaSize = 200000;
-
-    status_t finalStatus;
-
-    size_t cachedDataRemaining =
-            mCachedSource->approxDataRemaining(&finalStatus);
-
-    if (finalStatus != OK || (mMetaDataSize >= 0
-            && (off64_t)cachedDataRemaining >= mMetaDataSize)) {
-        ALOGV("stop caching, status %d, "
-                "metaDataSize %lld, cachedDataRemaining %zu",
-                finalStatus, mMetaDataSize, cachedDataRemaining);
-        return OK;
-    }
-
-    ALOGV("now cached %zu bytes of data", cachedDataRemaining);
-
-    if (mMetaDataSize < 0
-            && cachedDataRemaining >= kMinBytesForSniffing) {
-        String8 tmp;
-        float confidence;
-        sp<AMessage> meta;
-        if (!mCachedSource->sniff(&tmp, &confidence, &meta)) {
-            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()
-        mSniffedMIME = tmp.string();
-
-        if (meta == NULL
-                || !meta->findInt64("meta-data-size",
-                        reinterpret_cast<int64_t*>(&mMetaDataSize))) {
-            mMetaDataSize = kDefaultMetaSize;
-        }
-
-        if (mMetaDataSize < 0ll) {
-            ALOGE("invalid metaDataSize = %lld bytes", mMetaDataSize);
-            return UNKNOWN_ERROR;
-        }
-    }
-
-    return -EAGAIN;
-}
-
 void NuPlayer::GenericSource::start() {
     ALOGI("start");
 
     mStopRead = false;
     if (mAudioTrack.mSource != NULL) {
-        CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
-
         postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
     }
 
     if (mVideoTrack.mSource != NULL) {
-        CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
-
         postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
     }
 
     setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
     mStarted = true;
+
+    (new AMessage(kWhatStart, this))->post();
 }
 
 void NuPlayer::GenericSource::stop() {
     // nothing to do, just account for DRM playback status
     setDrmPlaybackStatusIfNeeded(Playback::STOP, 0);
     mStarted = false;
-    if (mIsWidevine) {
-        // For a widevine source we need to prevent any further reads.
-        sp<AMessage> msg = new AMessage(kWhatStopWidevine, id());
+    if (mIsWidevine || mIsSecure) {
+        // For widevine or secure sources we need to prevent any further reads.
+        sp<AMessage> msg = new AMessage(kWhatStopWidevine, this);
         sp<AMessage> response;
         (void) msg->postAndAwaitResponse(&response);
     }
@@ -495,6 +476,8 @@
     // nothing to do, just account for DRM playback status
     setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
     mStarted = true;
+
+    (new AMessage(kWhatResume, this))->post();
 }
 
 void NuPlayer::GenericSource::disconnect() {
@@ -521,28 +504,123 @@
 }
 
 void NuPlayer::GenericSource::schedulePollBuffering() {
-    sp<AMessage> msg = new AMessage(kWhatPollBuffering, id());
+    sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
     msg->setInt32("generation", mPollBufferingGeneration);
     msg->post(1000000ll);
 }
 
 void NuPlayer::GenericSource::cancelPollBuffering() {
+    mBuffering = false;
     ++mPollBufferingGeneration;
+    mPrevBufferPercentage = -1;
 }
 
-void NuPlayer::GenericSource::notifyBufferingUpdate(int percentage) {
+void NuPlayer::GenericSource::restartPollBuffering() {
+    if (mIsStreaming) {
+        cancelPollBuffering();
+        onPollBuffering();
+    }
+}
+
+void NuPlayer::GenericSource::notifyBufferingUpdate(int32_t percentage) {
+    // Buffering percent could go backward as it's estimated from remaining
+    // data and last access time. This could cause the buffering position
+    // drawn on media control to jitter slightly. Remember previously reported
+    // percentage and don't allow it to go backward.
+    if (percentage < mPrevBufferPercentage) {
+        percentage = mPrevBufferPercentage;
+    } else if (percentage > 100) {
+        percentage = 100;
+    }
+
+    mPrevBufferPercentage = percentage;
+
+    ALOGV("notifyBufferingUpdate: buffering %d%%", percentage);
+
     sp<AMessage> msg = dupNotify();
     msg->setInt32("what", kWhatBufferingUpdate);
     msg->setInt32("percentage", percentage);
     msg->post();
 }
 
+void NuPlayer::GenericSource::startBufferingIfNecessary() {
+    ALOGV("startBufferingIfNecessary: mPrepareBuffering=%d, mBuffering=%d",
+            mPrepareBuffering, mBuffering);
+
+    if (mPrepareBuffering) {
+        return;
+    }
+
+    if (!mBuffering) {
+        mBuffering = true;
+
+        ensureCacheIsFetching();
+        sendCacheStats();
+
+        sp<AMessage> notify = dupNotify();
+        notify->setInt32("what", kWhatPauseOnBufferingStart);
+        notify->post();
+    }
+}
+
+void NuPlayer::GenericSource::stopBufferingIfNecessary() {
+    ALOGV("stopBufferingIfNecessary: mPrepareBuffering=%d, mBuffering=%d",
+            mPrepareBuffering, mBuffering);
+
+    if (mPrepareBuffering) {
+        mPrepareBuffering = false;
+        notifyPrepared();
+        return;
+    }
+
+    if (mBuffering) {
+        mBuffering = false;
+
+        sendCacheStats();
+
+        sp<AMessage> notify = dupNotify();
+        notify->setInt32("what", kWhatResumeOnBufferingEnd);
+        notify->post();
+    }
+}
+
+void NuPlayer::GenericSource::sendCacheStats() {
+    int32_t kbps = 0;
+    status_t err = UNKNOWN_ERROR;
+
+    if (mWVMExtractor != NULL) {
+        err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps);
+    } else if (mCachedSource != NULL) {
+        err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
+    }
+
+    if (err == OK) {
+        sp<AMessage> notify = dupNotify();
+        notify->setInt32("what", kWhatCacheStats);
+        notify->setInt32("bandwidth", kbps);
+        notify->post();
+    }
+}
+
+void NuPlayer::GenericSource::ensureCacheIsFetching() {
+    if (mCachedSource != NULL) {
+        mCachedSource->resumeFetchingIfNecessary();
+    }
+}
+
 void NuPlayer::GenericSource::onPollBuffering() {
     status_t finalStatus = UNKNOWN_ERROR;
-    int64_t cachedDurationUs = 0ll;
+    int64_t cachedDurationUs = -1ll;
+    ssize_t cachedDataRemaining = -1;
 
-    if (mCachedSource != NULL) {
-        size_t cachedDataRemaining =
+    ALOGW_IF(mWVMExtractor != NULL && mCachedSource != NULL,
+            "WVMExtractor and NuCachedSource both present");
+
+    if (mWVMExtractor != NULL) {
+        cachedDurationUs =
+                mWVMExtractor->getCachedDurationUs(&finalStatus);
+    } else if (mCachedSource != NULL) {
+        cachedDataRemaining =
                 mCachedSource->approxDataRemaining(&finalStatus);
 
         if (finalStatus == OK) {
@@ -557,28 +635,50 @@
                 cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
             }
         }
-    } else if (mWVMExtractor != NULL) {
-        cachedDurationUs
-            = mWVMExtractor->getCachedDurationUs(&finalStatus);
     }
 
-    if (finalStatus == ERROR_END_OF_STREAM) {
-        notifyBufferingUpdate(100);
-        cancelPollBuffering();
-        return;
-    } else if (cachedDurationUs > 0ll && mDurationUs > 0ll) {
-        int percentage = 100.0 * cachedDurationUs / mDurationUs;
-        if (percentage > 100) {
-            percentage = 100;
+    if (finalStatus != OK) {
+        ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus);
+
+        if (finalStatus == ERROR_END_OF_STREAM) {
+            notifyBufferingUpdate(100);
         }
 
-        notifyBufferingUpdate(percentage);
+        stopBufferingIfNecessary();
+        return;
+    } else if (cachedDurationUs >= 0ll) {
+        if (mDurationUs > 0ll) {
+            int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs;
+            int percentage = 100.0 * cachedPosUs / mDurationUs;
+            if (percentage > 100) {
+                percentage = 100;
+            }
+
+            notifyBufferingUpdate(percentage);
+        }
+
+        ALOGV("onPollBuffering: cachedDurationUs %.1f sec",
+                cachedDurationUs / 1000000.0f);
+
+        if (cachedDurationUs < kLowWaterMarkUs) {
+            startBufferingIfNecessary();
+        } else if (cachedDurationUs > kHighWaterMarkUs) {
+            stopBufferingIfNecessary();
+        }
+    } else if (cachedDataRemaining >= 0) {
+        ALOGV("onPollBuffering: cachedDataRemaining %d bytes",
+                cachedDataRemaining);
+
+        if (cachedDataRemaining < kLowWaterMarkBytes) {
+            startBufferingIfNecessary();
+        } else if (cachedDataRemaining > kHighWaterMarkBytes) {
+            stopBufferingIfNecessary();
+        }
     }
 
     schedulePollBuffering();
 }
 
-
 void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
     switch (msg->what()) {
       case kWhatPrepareAsync:
@@ -644,23 +744,27 @@
           track->mSource->start();
           track->mIndex = trackIndex;
 
-          status_t avail;
-          if (!track->mPackets->hasBufferAvailable(&avail)) {
-              // sync from other source
-              TRESPASS();
-              break;
-          }
-
           int64_t timeUs, actualTimeUs;
           const bool formatChange = true;
-          sp<AMessage> latestMeta = track->mPackets->getLatestEnqueuedMeta();
-          CHECK(latestMeta != NULL && latestMeta->findInt64("timeUs", &timeUs));
+          if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
+              timeUs = mAudioLastDequeueTimeUs;
+          } else {
+              timeUs = mVideoLastDequeueTimeUs;
+          }
           readBuffer(trackType, timeUs, &actualTimeUs, formatChange);
           readBuffer(counterpartType, -1, NULL, formatChange);
           ALOGV("timeUs %lld actualTimeUs %lld", timeUs, actualTimeUs);
 
           break;
       }
+
+      case kWhatStart:
+      case kWhatResume:
+      {
+          restartPollBuffering();
+          break;
+      }
+
       case kWhatPollBuffering:
       {
           int32_t generation;
@@ -710,7 +814,7 @@
               mVideoTrack.mPackets->clear();
           }
           sp<AMessage> response = new AMessage;
-          uint32_t replyID;
+          sp<AReplyToken> replyID;
           CHECK(msg->senderAwaitsResponse(&replyID));
           response->postReply(replyID);
           break;
@@ -750,7 +854,7 @@
         const int64_t oneSecUs = 1000000ll;
         delayUs -= oneSecUs;
     }
-    sp<AMessage> msg2 = new AMessage(sendWhat, id());
+    sp<AMessage> msg2 = new AMessage(sendWhat, this);
     msg2->setInt32("generation", msgGeneration);
     msg2->post(delayUs < 0 ? 0 : delayUs);
 }
@@ -790,7 +894,7 @@
 }
 
 sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) {
-    sp<AMessage> msg = new AMessage(kWhatGetFormat, id());
+    sp<AMessage> msg = new AMessage(kWhatGetFormat, this);
     msg->setInt32("audio", audio);
 
     sp<AMessage> response;
@@ -812,7 +916,7 @@
     sp<MetaData> format = doGetFormatMeta(audio);
     response->setPointer("format", format.get());
 
-    uint32_t replyID;
+    sp<AReplyToken> replyID;
     CHECK(msg->senderAwaitsResponse(&replyID));
     response->postReply(replyID);
 }
@@ -842,7 +946,12 @@
 
     status_t finalResult;
     if (!track->mPackets->hasBufferAvailable(&finalResult)) {
-        return (finalResult == OK ? -EWOULDBLOCK : finalResult);
+        if (finalResult == OK) {
+            postReadBuffer(
+                    audio ? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
+            return -EWOULDBLOCK;
+        }
+        return finalResult;
     }
 
     status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
@@ -866,10 +975,15 @@
     int64_t timeUs;
     status_t eosResult; // ignored
     CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
+    if (audio) {
+        mAudioLastDequeueTimeUs = timeUs;
+    } else {
+        mVideoLastDequeueTimeUs = timeUs;
+    }
 
     if (mSubtitleTrack.mSource != NULL
             && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
-        sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id());
+        sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
         msg->setInt64("timeUs", timeUs);
         msg->setInt32("generation", mFetchSubtitleDataGeneration);
         msg->post();
@@ -877,7 +991,7 @@
 
     if (mTimedTextTrack.mSource != NULL
             && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
-        sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, id());
+        sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
         msg->setInt64("timeUs", timeUs);
         msg->setInt32("generation", mFetchTimedTextDataGeneration);
         msg->post();
@@ -942,7 +1056,7 @@
 }
 
 ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const {
-    sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, id());
+    sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this);
     msg->setInt32("type", type);
 
     sp<AMessage> response;
@@ -965,7 +1079,7 @@
     ssize_t index = doGetSelectedTrack(type);
     response->setInt32("index", index);
 
-    uint32_t replyID;
+    sp<AReplyToken> replyID;
     CHECK(msg->senderAwaitsResponse(&replyID));
     response->postReply(replyID);
 }
@@ -996,11 +1110,12 @@
     return -1;
 }
 
-status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) {
+status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
     ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
-    sp<AMessage> msg = new AMessage(kWhatSelectTrack, id());
+    sp<AMessage> msg = new AMessage(kWhatSelectTrack, this);
     msg->setInt32("trackIndex", trackIndex);
     msg->setInt32("select", select);
+    msg->setInt64("timeUs", timeUs);
 
     sp<AMessage> response;
     status_t err = msg->postAndAwaitResponse(&response);
@@ -1013,19 +1128,21 @@
 
 void NuPlayer::GenericSource::onSelectTrack(sp<AMessage> msg) {
     int32_t trackIndex, select;
+    int64_t timeUs;
     CHECK(msg->findInt32("trackIndex", &trackIndex));
     CHECK(msg->findInt32("select", &select));
+    CHECK(msg->findInt64("timeUs", &timeUs));
 
     sp<AMessage> response = new AMessage;
-    status_t err = doSelectTrack(trackIndex, select);
+    status_t err = doSelectTrack(trackIndex, select, timeUs);
     response->setInt32("err", err);
 
-    uint32_t replyID;
+    sp<AReplyToken> replyID;
     CHECK(msg->senderAwaitsResponse(&replyID));
     response->postReply(replyID);
 }
 
-status_t NuPlayer::GenericSource::doSelectTrack(size_t trackIndex, bool select) {
+status_t NuPlayer::GenericSource::doSelectTrack(size_t trackIndex, bool select, int64_t timeUs) {
     if (trackIndex >= mSources.size()) {
         return BAD_INDEX;
     }
@@ -1078,6 +1195,23 @@
             mFetchTimedTextDataGeneration++;
         }
 
+        status_t eosResult; // ignored
+        if (mSubtitleTrack.mSource != NULL
+                && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
+            sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
+            msg->setInt64("timeUs", timeUs);
+            msg->setInt32("generation", mFetchSubtitleDataGeneration);
+            msg->post();
+        }
+
+        if (mTimedTextTrack.mSource != NULL
+                && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
+            sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
+            msg->setInt64("timeUs", timeUs);
+            msg->setInt32("generation", mFetchTimedTextDataGeneration);
+            msg->post();
+        }
+
         return OK;
     } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
         bool audio = !strncasecmp(mime, "audio/", 6);
@@ -1086,7 +1220,7 @@
             return OK;
         }
 
-        sp<AMessage> msg = new AMessage(kWhatChangeAVSource, id());
+        sp<AMessage> msg = new AMessage(kWhatChangeAVSource, this);
         msg->setInt32("trackIndex", trackIndex);
         msg->post();
         return OK;
@@ -1096,7 +1230,7 @@
 }
 
 status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
-    sp<AMessage> msg = new AMessage(kWhatSeek, id());
+    sp<AMessage> msg = new AMessage(kWhatSeek, this);
     msg->setInt64("seekTimeUs", seekTimeUs);
 
     sp<AMessage> response;
@@ -1116,7 +1250,7 @@
     status_t err = doSeek(seekTimeUs);
     response->setInt32("err", err);
 
-    uint32_t replyID;
+    sp<AReplyToken> replyID;
     CHECK(msg->senderAwaitsResponse(&replyID));
     response->postReply(replyID);
 }
@@ -1132,22 +1266,32 @@
         readBuffer(MEDIA_TRACK_TYPE_VIDEO, seekTimeUs, &actualTimeUs);
 
         seekTimeUs = actualTimeUs;
+        mVideoLastDequeueTimeUs = seekTimeUs;
     }
 
     if (mAudioTrack.mSource != NULL) {
         readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs);
+        mAudioLastDequeueTimeUs = seekTimeUs;
     }
 
     setDrmPlaybackStatusIfNeeded(Playback::START, seekTimeUs / 1000);
     if (!mStarted) {
         setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0);
     }
+
+    // If currently buffering, post kWhatBufferingEnd first, so that
+    // NuPlayer resumes. Otherwise, if cache hits high watermark
+    // before new polling happens, no one will resume the playback.
+    stopBufferingIfNecessary();
+    restartPollBuffering();
+
     return OK;
 }
 
 sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer(
         MediaBuffer* mb,
         media_track_type trackType,
+        int64_t /* seekTimeUs */,
         int64_t *actualTimeUs) {
     bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
     size_t outLength = mb->range_length();
@@ -1157,7 +1301,7 @@
     }
 
     sp<ABuffer> ab;
-    if (mIsWidevine && !audio) {
+    if (mIsSecure && !audio) {
         // data is already provided in the buffer
         ab = new ABuffer(NULL, mb->range_length());
         mb->add_ref();
@@ -1185,6 +1329,16 @@
     CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs));
     meta->setInt64("timeUs", timeUs);
 
+#if 0
+    // Temporarily disable pre-roll till we have a full solution to handle
+    // both single seek and continous seek gracefully.
+    if (seekTimeUs > timeUs) {
+        sp<AMessage> extra = new AMessage;
+        extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
+        meta->setMessage("extra", extra);
+    }
+#endif
+
     if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
         const char *mime;
         CHECK(mTimedTextTrack.mSource != NULL
@@ -1216,7 +1370,7 @@
 
     if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
         mPendingReadBufferTypes |= (1 << trackType);
-        sp<AMessage> msg = new AMessage(kWhatReadBuffer, id());
+        sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
         msg->setInt32("trackType", trackType);
         msg->post();
     }
@@ -1226,14 +1380,13 @@
     int32_t tmpType;
     CHECK(msg->findInt32("trackType", &tmpType));
     media_track_type trackType = (media_track_type)tmpType;
+    readBuffer(trackType);
     {
         // only protect the variable change, as readBuffer may
-        // take considerable time.  This may result in one extra
-        // read being processed, but that is benign.
+        // take considerable time.
         Mutex::Autolock _l(mReadBufferLock);
         mPendingReadBufferTypes &= ~(1 << trackType);
     }
-    readBuffer(trackType);
 }
 
 void NuPlayer::GenericSource::readBuffer(
@@ -1286,7 +1439,7 @@
         seeking = true;
     }
 
-    if (mIsWidevine && trackType != MEDIA_TRACK_TYPE_AUDIO) {
+    if (mIsWidevine) {
         options.setNonBlocking();
     }
 
@@ -1317,7 +1470,8 @@
                 track->mPackets->queueDiscontinuity( type, NULL, true /* discard */);
             }
 
-            sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs);
+            sp<ABuffer> buffer = mediaBufferToABuffer(
+                    mbuf, trackType, seekTimeUs, actualTimeUs);
             track->mPackets->queueAccessUnit(buffer);
             formatChange = false;
             seeking = false;
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index f8601ea..5fc41ec 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -67,7 +67,7 @@
     virtual size_t getTrackCount() const;
     virtual sp<AMessage> getTrackInfo(size_t trackIndex) const;
     virtual ssize_t getSelectedTrack(media_track_type type) const;
-    virtual status_t selectTrack(size_t trackIndex, bool select);
+    virtual status_t selectTrack(size_t trackIndex, bool select, int64_t timeUs);
     virtual status_t seekTo(int64_t seekTimeUs);
 
     virtual status_t setBuffers(bool audio, Vector<MediaBuffer *> &buffers);
@@ -94,20 +94,23 @@
         kWhatSeek,
         kWhatReadBuffer,
         kWhatStopWidevine,
+        kWhatStart,
+        kWhatResume,
     };
 
-    Vector<sp<MediaSource> > mSources;
-
     struct Track {
         size_t mIndex;
         sp<MediaSource> mSource;
         sp<AnotherPacketSource> mPackets;
     };
 
+    Vector<sp<MediaSource> > mSources;
     Track mAudioTrack;
     int64_t mAudioTimeUs;
+    int64_t mAudioLastDequeueTimeUs;
     Track mVideoTrack;
     int64_t mVideoTimeUs;
+    int64_t mVideoLastDequeueTimeUs;
     Track mSubtitleTrack;
     Track mTimedTextTrack;
 
@@ -116,6 +119,8 @@
     int64_t mDurationUs;
     bool mAudioIsVorbis;
     bool mIsWidevine;
+    bool mIsSecure;
+    bool mIsStreaming;
     bool mUIDValid;
     uid_t mUID;
     sp<IMediaHTTPService> mHTTPService;
@@ -134,12 +139,13 @@
     sp<DecryptHandle> mDecryptHandle;
     bool mStarted;
     bool mStopRead;
-    String8 mContentType;
-    AString mSniffedMIME;
-    off64_t mMetaDataSize;
     int64_t mBitrate;
     int32_t mPollBufferingGeneration;
     uint32_t mPendingReadBufferTypes;
+    bool mBuffering;
+    bool mPrepareBuffering;
+    int32_t mPrevBufferPercentage;
+
     mutable Mutex mReadBufferLock;
 
     sp<ALooper> mLooper;
@@ -151,8 +157,6 @@
     int64_t getLastReadPosition();
     void setDrmPlaybackStatusIfNeeded(int playbackStatus, int64_t position);
 
-    status_t prefillCacheIfNecessary();
-
     void notifyPreparedAndCleanup(status_t err);
 
     void onGetFormatMeta(sp<AMessage> msg) const;
@@ -162,7 +166,7 @@
     ssize_t doGetSelectedTrack(media_track_type type) const;
 
     void onSelectTrack(sp<AMessage> msg);
-    status_t doSelectTrack(size_t trackIndex, bool select);
+    status_t doSelectTrack(size_t trackIndex, bool select, int64_t timeUs);
 
     void onSeek(sp<AMessage> msg);
     status_t doSeek(int64_t seekTimeUs);
@@ -180,6 +184,7 @@
     sp<ABuffer> mediaBufferToABuffer(
             MediaBuffer *mbuf,
             media_track_type trackType,
+            int64_t seekTimeUs,
             int64_t *actualTimeUs = NULL);
 
     void postReadBuffer(media_track_type trackType);
@@ -190,8 +195,13 @@
 
     void schedulePollBuffering();
     void cancelPollBuffering();
+    void restartPollBuffering();
     void onPollBuffering();
-    void notifyBufferingUpdate(int percentage);
+    void notifyBufferingUpdate(int32_t percentage);
+    void startBufferingIfNecessary();
+    void stopBufferingIfNecessary();
+    void sendCacheStats();
+    void ensureCacheIsFetching();
 
     DISALLOW_EVIL_CONSTRUCTORS(GenericSource);
 };
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index a003c81..d01e83a 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -81,7 +81,7 @@
         mLiveLooper->registerHandler(this);
     }
 
-    sp<AMessage> notify = new AMessage(kWhatSessionNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatSessionNotify, this);
 
     mLiveSession = new LiveSession(
             notify,
@@ -98,6 +98,10 @@
 }
 
 sp<AMessage> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
+    if (mLiveSession == NULL) {
+        return NULL;
+    }
+
     sp<AMessage> format;
     status_t err = mLiveSession->getStreamFormat(
             audio ? LiveSession::STREAMTYPE_AUDIO
@@ -135,13 +139,21 @@
     return mLiveSession->getTrackInfo(trackIndex);
 }
 
-status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select) {
+ssize_t NuPlayer::HTTPLiveSource::getSelectedTrack(media_track_type type) const {
+    if (mLiveSession == NULL) {
+        return -1;
+    } else {
+        return mLiveSession->getSelectedTrack(type);
+    }
+}
+
+status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
     status_t err = mLiveSession->selectTrack(trackIndex, select);
 
     if (err == OK) {
         mFetchSubtitleDataGeneration++;
         if (select) {
-            sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id());
+            sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
             msg->setInt32("generation", mFetchSubtitleDataGeneration);
             msg->post();
         }
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
index 6b5f6af..bbb8981 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -42,7 +42,8 @@
     virtual status_t getDuration(int64_t *durationUs);
     virtual size_t getTrackCount() const;
     virtual sp<AMessage> getTrackInfo(size_t trackIndex) const;
-    virtual status_t selectTrack(size_t trackIndex, bool select);
+    virtual ssize_t getSelectedTrack(media_track_type /* type */) const;
+    virtual status_t selectTrack(size_t trackIndex, bool select, int64_t timeUs);
     virtual status_t seekTo(int64_t seekTimeUs);
 
 protected:
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 47bd989..f4d3794 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -21,7 +21,9 @@
 #include "NuPlayer.h"
 
 #include "HTTPLiveSource.h"
+#include "NuPlayerCCDecoder.h"
 #include "NuPlayerDecoder.h"
+#include "NuPlayerDecoderBase.h"
 #include "NuPlayerDecoderPassThrough.h"
 #include "NuPlayerDriver.h"
 #include "NuPlayerRenderer.h"
@@ -33,6 +35,8 @@
 
 #include "ATSParser.h"
 
+#include <cutils/properties.h>
+
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -50,10 +54,6 @@
 
 namespace android {
 
-// TODO optimize buffer size for power consumption
-// The offload read buffer size is 32 KB but 24 KB uses less power.
-const size_t NuPlayer::kAggregateBufferSizeBytes = 24 * 1024;
-
 struct NuPlayer::Action : public RefBase {
     Action() {}
 
@@ -80,6 +80,21 @@
     DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
 };
 
+struct NuPlayer::ResumeDecoderAction : public Action {
+    ResumeDecoderAction(bool needNotify)
+        : mNeedNotify(needNotify) {
+    }
+
+    virtual void execute(NuPlayer *player) {
+        player->performResumeDecoders(mNeedNotify);
+    }
+
+private:
+    bool mNeedNotify;
+
+    DISALLOW_EVIL_CONSTRUCTORS(ResumeDecoderAction);
+};
+
 struct NuPlayer::SetSurfaceAction : public Action {
     SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper)
         : mWrapper(wrapper) {
@@ -151,7 +166,6 @@
 NuPlayer::NuPlayer()
     : mUIDValid(false),
       mSourceFlags(0),
-      mVideoIsAVC(false),
       mOffloadAudio(false),
       mAudioDecoderGeneration(0),
       mVideoDecoderGeneration(0),
@@ -162,15 +176,14 @@
       mScanSourcesGeneration(0),
       mPollDurationGeneration(0),
       mTimedTextGeneration(0),
-      mTimeDiscontinuityPending(false),
       mFlushingAudio(NONE),
       mFlushingVideo(NONE),
-      mSkipRenderingAudioUntilMediaTimeUs(-1ll),
-      mSkipRenderingVideoUntilMediaTimeUs(-1ll),
-      mNumFramesTotal(0ll),
-      mNumFramesDropped(0ll),
+      mResumePending(false),
       mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
-      mStarted(false) {
+      mPlaybackRate(1.0),
+      mStarted(false),
+      mPaused(false),
+      mPausedByClient(false) {
     clearFlushComplete();
 }
 
@@ -187,9 +200,9 @@
 }
 
 void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
-    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
 
-    sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
 
     msg->setObject("source", new StreamingSource(notify, source));
     msg->post();
@@ -217,10 +230,10 @@
         const char *url,
         const KeyedVector<String8, String8> *headers) {
 
-    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
     size_t len = strlen(url);
 
-    sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
 
     sp<Source> source;
     if (IsHTTPLiveURL(url)) {
@@ -254,9 +267,9 @@
 }
 
 void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
-    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
 
-    sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
 
     sp<GenericSource> source =
             new GenericSource(notify, mUIDValid, mUID);
@@ -273,12 +286,12 @@
 }
 
 void NuPlayer::prepareAsync() {
-    (new AMessage(kWhatPrepare, id()))->post();
+    (new AMessage(kWhatPrepare, this))->post();
 }
 
 void NuPlayer::setVideoSurfaceTextureAsync(
         const sp<IGraphicBufferProducer> &bufferProducer) {
-    sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
+    sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, this);
 
     if (bufferProducer == NULL) {
         msg->setObject("native-window", NULL);
@@ -293,17 +306,23 @@
 }
 
 void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
-    sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
+    sp<AMessage> msg = new AMessage(kWhatSetAudioSink, this);
     msg->setObject("sink", sink);
     msg->post();
 }
 
 void NuPlayer::start() {
-    (new AMessage(kWhatStart, id()))->post();
+    (new AMessage(kWhatStart, this))->post();
+}
+
+void NuPlayer::setPlaybackRate(float rate) {
+    sp<AMessage> msg = new AMessage(kWhatSetRate, this);
+    msg->setFloat("rate", rate);
+    msg->post();
 }
 
 void NuPlayer::pause() {
-    (new AMessage(kWhatPause, id()))->post();
+    (new AMessage(kWhatPause, this))->post();
 }
 
 void NuPlayer::resetAsync() {
@@ -317,11 +336,11 @@
         mSource->disconnect();
     }
 
-    (new AMessage(kWhatReset, id()))->post();
+    (new AMessage(kWhatReset, this))->post();
 }
 
 void NuPlayer::seekToAsync(int64_t seekTimeUs, bool needNotify) {
-    sp<AMessage> msg = new AMessage(kWhatSeek, id());
+    sp<AMessage> msg = new AMessage(kWhatSeek, this);
     msg->setInt64("seekTimeUs", seekTimeUs);
     msg->setInt32("needNotify", needNotify);
     msg->post();
@@ -389,7 +408,7 @@
 
         case kWhatGetTrackInfo:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             Parcel* reply;
@@ -442,7 +461,7 @@
             sp<AMessage> response = new AMessage;
             response->setInt32("err", err);
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
             response->postReply(replyID);
             break;
@@ -450,13 +469,15 @@
 
         case kWhatSelectTrack:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             size_t trackIndex;
             int32_t select;
+            int64_t timeUs;
             CHECK(msg->findSize("trackIndex", &trackIndex));
             CHECK(msg->findInt32("select", &select));
+            CHECK(msg->findInt64("timeUs", &timeUs));
 
             status_t err = INVALID_OPERATION;
 
@@ -470,7 +491,7 @@
             }
 
             if (trackIndex < inbandTracks) {
-                err = mSource->selectTrack(trackIndex, select);
+                err = mSource->selectTrack(trackIndex, select, timeUs);
 
                 if (!select && err == OK) {
                     int32_t type;
@@ -525,7 +546,7 @@
             sp<RefBase> obj;
             CHECK(msg->findObject("native-window", &obj));
 
-            if (mSource->getFormat(false /* audio */) == NULL) {
+            if (mSource == NULL || mSource->getFormat(false /* audio */) == NULL) {
                 performSetSurface(static_cast<NativeWindowWrapper *>(obj.get()));
                 break;
             }
@@ -557,6 +578,12 @@
                         new SimpleAction(&NuPlayer::performScanSources));
             }
 
+            // After a flush without shutdown, decoder is paused.
+            // Don't resume it until source seek is done, otherwise it could
+            // start pulling stale data too soon.
+            mDeferredActions.push_back(
+                    new ResumeDecoderAction(false /* needNotify */));
+
             processDeferredActions();
             break;
         }
@@ -580,6 +607,17 @@
             } else {
                 onStart();
             }
+            mPausedByClient = false;
+            break;
+        }
+
+        case kWhatSetRate:
+        {
+            ALOGV("kWhatSetRate");
+            CHECK(msg->findFloat("rate", &mPlaybackRate));
+            if (mRenderer != NULL) {
+                mRenderer->setPlaybackRate(mPlaybackRate);
+            }
             break;
         }
 
@@ -606,11 +644,21 @@
                 instantiateDecoder(false, &mVideoDecoder);
             }
 
-            if (mAudioSink != NULL) {
-                if (mOffloadAudio) {
+            // Don't try to re-open audio sink if there's an existing decoder.
+            if (mAudioSink != NULL && mAudioDecoder == NULL) {
+                sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
+                sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
+                audio_stream_type_t streamType = mAudioSink->getAudioStreamType();
+                const bool hasVideo = (videoFormat != NULL);
+                const bool canOffload = canOffloadStream(
+                        audioMeta, hasVideo, true /* is_streaming */, streamType);
+                if (canOffload) {
+                    if (!mOffloadAudio) {
+                        mRenderer->signalEnableOffloadAudio();
+                    }
                     // open audio sink early under offload mode.
                     sp<AMessage> format = mSource->getFormat(true /*audio*/);
-                    openAudioSink(format, true /*offloadOnly*/);
+                    tryOpenAudioSinkForOffload(format, hasVideo);
                 }
                 instantiateDecoder(true, &mAudioDecoder);
             }
@@ -674,16 +722,26 @@
             int32_t what;
             CHECK(msg->findInt32("what", &what));
 
-            if (what == Decoder::kWhatFillThisBuffer) {
-                status_t err = feedDecoderInputData(
-                        audio, msg);
+            if (what == DecoderBase::kWhatInputDiscontinuity) {
+                int32_t formatChange;
+                CHECK(msg->findInt32("formatChange", &formatChange));
 
-                if (err == -EWOULDBLOCK) {
-                    if (mSource->feedMoreTSData() == OK) {
-                        msg->post(10 * 1000ll);
-                    }
+                ALOGV("%s discontinuity: formatChange %d",
+                        audio ? "audio" : "video", formatChange);
+
+                if (formatChange) {
+                    mDeferredActions.push_back(
+                            new FlushDecoderAction(
+                                audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
+                                audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN));
                 }
-            } else if (what == Decoder::kWhatEOS) {
+
+                mDeferredActions.push_back(
+                        new SimpleAction(
+                                &NuPlayer::performScanSources));
+
+                processDeferredActions();
+            } else if (what == DecoderBase::kWhatEOS) {
                 int32_t err;
                 CHECK(msg->findInt32("err", &err));
 
@@ -696,25 +754,20 @@
                 }
 
                 mRenderer->queueEOS(audio, err);
-            } else if (what == Decoder::kWhatFlushCompleted) {
+            } else if (what == DecoderBase::kWhatFlushCompleted) {
                 ALOGV("decoder %s flush completed", audio ? "audio" : "video");
 
                 handleFlushComplete(audio, true /* isDecoder */);
                 finishFlushIfPossible();
-            } else if (what == Decoder::kWhatOutputFormatChanged) {
+            } else if (what == DecoderBase::kWhatVideoSizeChanged) {
                 sp<AMessage> format;
                 CHECK(msg->findMessage("format", &format));
 
-                if (audio) {
-                    openAudioSink(format, false /*offloadOnly*/);
-                } else {
-                    // video
-                    sp<AMessage> inputFormat =
-                            mSource->getFormat(false /* audio */);
+                sp<AMessage> inputFormat =
+                        mSource->getFormat(false /* audio */);
 
-                    updateVideoSize(inputFormat, format);
-                }
-            } else if (what == Decoder::kWhatShutdownCompleted) {
+                updateVideoSize(inputFormat, format);
+            } else if (what == DecoderBase::kWhatShutdownCompleted) {
                 ALOGV("%s shutdown completed", audio ? "audio" : "video");
                 if (audio) {
                     mAudioDecoder.clear();
@@ -731,7 +784,9 @@
                 }
 
                 finishFlushIfPossible();
-            } else if (what == Decoder::kWhatError) {
+            } else if (what == DecoderBase::kWhatResumeCompleted) {
+                finishResume();
+            } else if (what == DecoderBase::kWhatError) {
                 status_t err;
                 if (!msg->findInt32("err", &err) || err == OK) {
                     err = UNKNOWN_ERROR;
@@ -740,6 +795,8 @@
                 // Decoder errors can be due to Source (e.g. from streaming),
                 // or from decoding corrupted bitstreams, or from other decoder
                 // MediaCodec operations (e.g. from an ongoing reset or seek).
+                // They may also be due to openAudioSink failure at
+                // decoder start or after a format change.
                 //
                 // We try to gracefully shut down the affected decoder if possible,
                 // rather than trying to force the shutdown with something
@@ -779,8 +836,6 @@
                         break;                    // Finish anyways.
                 }
                 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
-            } else if (what == Decoder::kWhatDrainThisBuffer) {
-                renderBuffer(audio, msg);
             } else {
                 ALOGV("Unhandled decoder notification %d '%c%c%c%c'.",
                       what,
@@ -846,7 +901,7 @@
                 ALOGV("media rendering started");
                 notifyListener(MEDIA_STARTED, 0, 0);
             } else if (what == Renderer::kWhatAudioOffloadTearDown) {
-                ALOGV("Tear down audio offload, fall back to s/w path");
+                ALOGV("Tear down audio offload, fall back to s/w path if due to error.");
                 int64_t positionUs;
                 CHECK(msg->findInt64("positionUs", &positionUs));
                 int32_t reason;
@@ -854,15 +909,17 @@
                 closeAudioSink();
                 mAudioDecoder.clear();
                 ++mAudioDecoderGeneration;
-                mRenderer->flush(true /* audio */);
+                mRenderer->flush(
+                        true /* audio */, false /* notifyComplete */);
                 if (mVideoDecoder != NULL) {
-                    mRenderer->flush(false /* audio */);
+                    mRenderer->flush(
+                            false /* audio */, false /* notifyComplete */);
                 }
-                mRenderer->signalDisableOffloadAudio();
-                mOffloadAudio = false;
 
                 performSeek(positionUs, false /* needNotify */);
                 if (reason == Renderer::kDueToError) {
+                    mRenderer->signalDisableOffloadAudio();
+                    mOffloadAudio = false;
                     instantiateDecoder(true /* audio */, &mAudioDecoder);
                 }
             }
@@ -907,22 +964,20 @@
             mDeferredActions.push_back(
                     new SeekAction(seekTimeUs, needNotify));
 
+            // After a flush without shutdown, decoder is paused.
+            // Don't resume it until source seek is done, otherwise it could
+            // start pulling stale data too soon.
+            mDeferredActions.push_back(
+                    new ResumeDecoderAction(needNotify));
+
             processDeferredActions();
             break;
         }
 
         case kWhatPause:
         {
-            if (mSource != NULL) {
-                mSource->pause();
-            } else {
-                ALOGW("pause called when source is gone or not set");
-            }
-            if (mRenderer != NULL) {
-                mRenderer->pause();
-            } else {
-                ALOGW("pause called when renderer is gone or not set");
-            }
+            onPause();
+            mPausedByClient = true;
             break;
         }
 
@@ -945,6 +1000,10 @@
 }
 
 void NuPlayer::onResume() {
+    if (!mPaused) {
+        return;
+    }
+    mPaused = false;
     if (mSource != NULL) {
         mSource->resume();
     } else {
@@ -963,14 +1022,9 @@
 }
 
 void NuPlayer::onStart() {
-    mVideoIsAVC = false;
     mOffloadAudio = false;
     mAudioEOS = false;
     mVideoEOS = false;
-    mSkipRenderingAudioUntilMediaTimeUs = -1;
-    mSkipRenderingVideoUntilMediaTimeUs = -1;
-    mNumFramesTotal = 0;
-    mNumFramesDropped = 0;
     mStarted = true;
 
     /* instantiate decoders now for secure playback */
@@ -1007,15 +1061,17 @@
         flags |= Renderer::FLAG_OFFLOAD_AUDIO;
     }
 
-    sp<AMessage> notify = new AMessage(kWhatRendererNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatRendererNotify, this);
     ++mRendererGeneration;
     notify->setInt32("generation", mRendererGeneration);
     mRenderer = new Renderer(mAudioSink, notify, flags);
-
     mRendererLooper = new ALooper;
     mRendererLooper->setName("NuPlayerRenderer");
     mRendererLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
     mRendererLooper->registerHandler(mRenderer);
+    if (mPlaybackRate != 1.0) {
+        mRenderer->setPlaybackRate(mPlaybackRate);
+    }
 
     sp<MetaData> meta = getFileMeta();
     int32_t rate;
@@ -1024,9 +1080,33 @@
         mRenderer->setVideoFrameRate(rate);
     }
 
+    if (mVideoDecoder != NULL) {
+        mVideoDecoder->setRenderer(mRenderer);
+    }
+    if (mAudioDecoder != NULL) {
+        mAudioDecoder->setRenderer(mRenderer);
+    }
+
     postScanSources();
 }
 
+void NuPlayer::onPause() {
+    if (mPaused) {
+        return;
+    }
+    mPaused = true;
+    if (mSource != NULL) {
+        mSource->pause();
+    } else {
+        ALOGW("pause called when source is gone or not set");
+    }
+    if (mRenderer != NULL) {
+        mRenderer->pause();
+    } else {
+        ALOGW("pause called when renderer is gone or not set");
+    }
+}
+
 bool NuPlayer::audioDecoderStillNeeded() {
     // Audio decoder is no longer needed if it's in shut/shutting down status.
     return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER));
@@ -1084,22 +1164,6 @@
 
     ALOGV("both audio and video are flushed now.");
 
-    mPendingAudioAccessUnit.clear();
-    mAggregateBuffer.clear();
-
-    if (mTimeDiscontinuityPending) {
-        mRenderer->signalTimeDiscontinuity();
-        mTimeDiscontinuityPending = false;
-    }
-
-    if (mAudioDecoder != NULL && mFlushingAudio == FLUSHED) {
-        mAudioDecoder->signalResume();
-    }
-
-    if (mVideoDecoder != NULL && mFlushingVideo == FLUSHED) {
-        mVideoDecoder->signalResume();
-    }
-
     mFlushingAudio = NONE;
     mFlushingVideo = NONE;
 
@@ -1113,35 +1177,23 @@
         return;
     }
 
-    sp<AMessage> msg = new AMessage(kWhatScanSources, id());
+    sp<AMessage> msg = new AMessage(kWhatScanSources, this);
     msg->setInt32("generation", mScanSourcesGeneration);
     msg->post();
 
     mScanSourcesPending = true;
 }
 
-void NuPlayer::openAudioSink(const sp<AMessage> &format, bool offloadOnly) {
-    uint32_t flags;
-    int64_t durationUs;
-    bool hasVideo = (mVideoDecoder != NULL);
-    // FIXME: we should handle the case where the video decoder
-    // is created after we receive the format change indication.
-    // Current code will just make that we select deep buffer
-    // with video which should not be a problem as it should
-    // not prevent from keeping A/V sync.
-    if (!hasVideo &&
-            mSource->getDuration(&durationUs) == OK &&
-            durationUs
-                > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
-        flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
-    } else {
-        flags = AUDIO_OUTPUT_FLAG_NONE;
-    }
+void NuPlayer::tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo) {
+    // Note: This is called early in NuPlayer to determine whether offloading
+    // is possible; otherwise the decoders call the renderer openAudioSink directly.
 
-    mOffloadAudio = mRenderer->openAudioSink(
-            format, offloadOnly, hasVideo, flags);
-
-    if (mOffloadAudio) {
+    status_t err = mRenderer->openAudioSink(
+            format, true /* offloadOnly */, hasVideo, AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio);
+    if (err != OK) {
+        // Any failure we turn off mOffloadAudio.
+        mOffloadAudio = false;
+    } else if (mOffloadAudio) {
         sp<MetaData> audioMeta =
                 mSource->getFormatMeta(true /* audio */);
         sendMetaDataToHal(mAudioSink, audioMeta);
@@ -1152,7 +1204,7 @@
     mRenderer->closeAudioSink();
 }
 
-status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
+status_t NuPlayer::instantiateDecoder(bool audio, sp<DecoderBase> *decoder) {
     if (*decoder != NULL) {
         return OK;
     }
@@ -1166,32 +1218,49 @@
     if (!audio) {
         AString mime;
         CHECK(format->findString("mime", &mime));
-        mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
 
-        sp<AMessage> ccNotify = new AMessage(kWhatClosedCaptionNotify, id());
-        mCCDecoder = new CCDecoder(ccNotify);
+        sp<AMessage> ccNotify = new AMessage(kWhatClosedCaptionNotify, this);
+        if (mCCDecoder == NULL) {
+            mCCDecoder = new CCDecoder(ccNotify);
+        }
 
         if (mSourceFlags & Source::FLAG_SECURE) {
             format->setInt32("secure", true);
         }
+
+        if (mSourceFlags & Source::FLAG_PROTECTED) {
+            format->setInt32("protected", true);
+        }
     }
 
     if (audio) {
-        sp<AMessage> notify = new AMessage(kWhatAudioNotify, id());
+        sp<AMessage> notify = new AMessage(kWhatAudioNotify, this);
         ++mAudioDecoderGeneration;
         notify->setInt32("generation", mAudioDecoderGeneration);
 
         if (mOffloadAudio) {
-            *decoder = new DecoderPassThrough(notify);
+            *decoder = new DecoderPassThrough(notify, mSource, mRenderer);
         } else {
-            *decoder = new Decoder(notify);
+            *decoder = new Decoder(notify, mSource, mRenderer);
         }
     } else {
-        sp<AMessage> notify = new AMessage(kWhatVideoNotify, id());
+        sp<AMessage> notify = new AMessage(kWhatVideoNotify, this);
         ++mVideoDecoderGeneration;
         notify->setInt32("generation", mVideoDecoderGeneration);
 
-        *decoder = new Decoder(notify, mNativeWindow);
+        *decoder = new Decoder(
+                notify, mSource, mRenderer, mNativeWindow, mCCDecoder);
+
+        // enable FRC if high-quality AV sync is requested, even if not
+        // queuing to native window, as this will even improve textureview
+        // playback.
+        {
+            char value[PROPERTY_VALUE_MAX];
+            if (property_get("persist.sys.media.avsync", value, NULL) &&
+                    (!strcmp("1", value) || !strcasecmp("true", value))) {
+                format->setInt32("auto-frc", 1);
+            }
+        }
     }
     (*decoder)->init();
     (*decoder)->configure(format);
@@ -1221,281 +1290,6 @@
     return OK;
 }
 
-status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
-    sp<AMessage> reply;
-    CHECK(msg->findMessage("reply", &reply));
-
-    if ((audio && mFlushingAudio != NONE)
-            || (!audio && mFlushingVideo != NONE)
-            || mSource == NULL) {
-        reply->setInt32("err", INFO_DISCONTINUITY);
-        reply->post();
-        return OK;
-    }
-
-    sp<ABuffer> accessUnit;
-
-    // Aggregate smaller buffers into a larger buffer.
-    // The goal is to reduce power consumption.
-    // Note this will not work if the decoder requires one frame per buffer.
-    bool doBufferAggregation = (audio && mOffloadAudio);
-    bool needMoreData = false;
-
-    bool dropAccessUnit;
-    do {
-        status_t err;
-        // Did we save an accessUnit earlier because of a discontinuity?
-        if (audio && (mPendingAudioAccessUnit != NULL)) {
-            accessUnit = mPendingAudioAccessUnit;
-            mPendingAudioAccessUnit.clear();
-            err = mPendingAudioErr;
-            ALOGV("feedDecoderInputData() use mPendingAudioAccessUnit");
-        } else {
-            err = mSource->dequeueAccessUnit(audio, &accessUnit);
-        }
-
-        if (err == -EWOULDBLOCK) {
-            return err;
-        } else if (err != OK) {
-            if (err == INFO_DISCONTINUITY) {
-                if (doBufferAggregation && (mAggregateBuffer != NULL)) {
-                    // We already have some data so save this for later.
-                    mPendingAudioErr = err;
-                    mPendingAudioAccessUnit = accessUnit;
-                    accessUnit.clear();
-                    ALOGD("feedDecoderInputData() save discontinuity for later");
-                    break;
-                }
-                int32_t type;
-                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
-
-                bool formatChange =
-                    (audio &&
-                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
-                    || (!audio &&
-                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
-
-                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
-
-                ALOGI("%s discontinuity (formatChange=%d, time=%d)",
-                     audio ? "audio" : "video", formatChange, timeChange);
-
-                if (audio) {
-                    mSkipRenderingAudioUntilMediaTimeUs = -1;
-                } else {
-                    mSkipRenderingVideoUntilMediaTimeUs = -1;
-                }
-
-                if (timeChange) {
-                    sp<AMessage> extra;
-                    if (accessUnit->meta()->findMessage("extra", &extra)
-                            && extra != NULL) {
-                        int64_t resumeAtMediaTimeUs;
-                        if (extra->findInt64(
-                                    "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
-                            ALOGI("suppressing rendering of %s until %lld us",
-                                    audio ? "audio" : "video", resumeAtMediaTimeUs);
-
-                            if (audio) {
-                                mSkipRenderingAudioUntilMediaTimeUs =
-                                    resumeAtMediaTimeUs;
-                            } else {
-                                mSkipRenderingVideoUntilMediaTimeUs =
-                                    resumeAtMediaTimeUs;
-                            }
-                        }
-                    }
-                }
-
-                mTimeDiscontinuityPending =
-                    mTimeDiscontinuityPending || timeChange;
-
-                bool seamlessFormatChange = false;
-                sp<AMessage> newFormat = mSource->getFormat(audio);
-                if (formatChange) {
-                    seamlessFormatChange =
-                        getDecoder(audio)->supportsSeamlessFormatChange(newFormat);
-                    // treat seamless format change separately
-                    formatChange = !seamlessFormatChange;
-                }
-                bool shutdownOrFlush = formatChange || timeChange;
-
-                // We want to queue up scan-sources only once per discontinuity.
-                // We control this by doing it only if neither audio nor video are
-                // flushing or shutting down.  (After handling 1st discontinuity, one
-                // of the flushing states will not be NONE.)
-                // No need to scan sources if this discontinuity does not result
-                // in a flush or shutdown, as the flushing state will stay NONE.
-                if (mFlushingAudio == NONE && mFlushingVideo == NONE &&
-                        shutdownOrFlush) {
-                    // And we'll resume scanning sources once we're done
-                    // flushing.
-                    mDeferredActions.push_front(
-                            new SimpleAction(
-                                &NuPlayer::performScanSources));
-                }
-
-                if (formatChange /* not seamless */) {
-                    // must change decoder
-                    flushDecoder(audio, /* needShutdown = */ true);
-                } else if (timeChange) {
-                    // need to flush
-                    flushDecoder(audio, /* needShutdown = */ false, newFormat);
-                    err = OK;
-                } else if (seamlessFormatChange) {
-                    // reuse existing decoder and don't flush
-                    updateDecoderFormatWithoutFlush(audio, newFormat);
-                    err = OK;
-                } else {
-                    // This stream is unaffected by the discontinuity
-                    return -EWOULDBLOCK;
-                }
-            }
-
-            reply->setInt32("err", err);
-            reply->post();
-            return OK;
-        }
-
-        if (!audio) {
-            ++mNumFramesTotal;
-        }
-
-        dropAccessUnit = false;
-        if (!audio
-                && !(mSourceFlags & Source::FLAG_SECURE)
-                && mRenderer->getVideoLateByUs() > 100000ll
-                && mVideoIsAVC
-                && !IsAVCReferenceFrame(accessUnit)) {
-            dropAccessUnit = true;
-            ++mNumFramesDropped;
-        }
-
-        size_t smallSize = accessUnit->size();
-        needMoreData = false;
-        if (doBufferAggregation && (mAggregateBuffer == NULL)
-                // Don't bother if only room for a few small buffers.
-                && (smallSize < (kAggregateBufferSizeBytes / 3))) {
-            // Create a larger buffer for combining smaller buffers from the extractor.
-            mAggregateBuffer = new ABuffer(kAggregateBufferSizeBytes);
-            mAggregateBuffer->setRange(0, 0); // start empty
-        }
-
-        if (doBufferAggregation && (mAggregateBuffer != NULL)) {
-            int64_t timeUs;
-            int64_t dummy;
-            bool smallTimestampValid = accessUnit->meta()->findInt64("timeUs", &timeUs);
-            bool bigTimestampValid = mAggregateBuffer->meta()->findInt64("timeUs", &dummy);
-            // Will the smaller buffer fit?
-            size_t bigSize = mAggregateBuffer->size();
-            size_t roomLeft = mAggregateBuffer->capacity() - bigSize;
-            // Should we save this small buffer for the next big buffer?
-            // If the first small buffer did not have a timestamp then save
-            // any buffer that does have a timestamp until the next big buffer.
-            if ((smallSize > roomLeft)
-                || (!bigTimestampValid && (bigSize > 0) && smallTimestampValid)) {
-                mPendingAudioErr = err;
-                mPendingAudioAccessUnit = accessUnit;
-                accessUnit.clear();
-            } else {
-                // Grab time from first small buffer if available.
-                if ((bigSize == 0) && smallTimestampValid) {
-                    mAggregateBuffer->meta()->setInt64("timeUs", timeUs);
-                }
-                // Append small buffer to the bigger buffer.
-                memcpy(mAggregateBuffer->base() + bigSize, accessUnit->data(), smallSize);
-                bigSize += smallSize;
-                mAggregateBuffer->setRange(0, bigSize);
-
-                // Keep looping until we run out of room in the mAggregateBuffer.
-                needMoreData = true;
-
-                ALOGV("feedDecoderInputData() smallSize = %zu, bigSize = %zu, capacity = %zu",
-                        smallSize, bigSize, mAggregateBuffer->capacity());
-            }
-        }
-    } while (dropAccessUnit || needMoreData);
-
-    // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
-
-#if 0
-    int64_t mediaTimeUs;
-    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
-    ALOGV("feeding %s input buffer at media time %.2f secs",
-         audio ? "audio" : "video",
-         mediaTimeUs / 1E6);
-#endif
-
-    if (!audio) {
-        mCCDecoder->decode(accessUnit);
-    }
-
-    if (doBufferAggregation && (mAggregateBuffer != NULL)) {
-        ALOGV("feedDecoderInputData() reply with aggregated buffer, %zu",
-                mAggregateBuffer->size());
-        reply->setBuffer("buffer", mAggregateBuffer);
-        mAggregateBuffer.clear();
-    } else {
-        reply->setBuffer("buffer", accessUnit);
-    }
-
-    reply->post();
-
-    return OK;
-}
-
-void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
-    // ALOGV("renderBuffer %s", audio ? "audio" : "video");
-
-    sp<AMessage> reply;
-    CHECK(msg->findMessage("reply", &reply));
-
-    if ((audio && mFlushingAudio != NONE)
-            || (!audio && mFlushingVideo != NONE)) {
-        // We're currently attempting to flush the decoder, in order
-        // to complete this, the decoder wants all its buffers back,
-        // so we don't want any output buffers it sent us (from before
-        // we initiated the flush) to be stuck in the renderer's queue.
-
-        ALOGV("we're still flushing the %s decoder, sending its output buffer"
-             " right back.", audio ? "audio" : "video");
-
-        reply->post();
-        return;
-    }
-
-    sp<ABuffer> buffer;
-    CHECK(msg->findBuffer("buffer", &buffer));
-
-    int64_t mediaTimeUs;
-    CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
-
-    int64_t &skipUntilMediaTimeUs =
-        audio
-            ? mSkipRenderingAudioUntilMediaTimeUs
-            : mSkipRenderingVideoUntilMediaTimeUs;
-
-    if (skipUntilMediaTimeUs >= 0) {
-
-        if (mediaTimeUs < skipUntilMediaTimeUs) {
-            ALOGV("dropping %s buffer at time %lld as requested.",
-                 audio ? "audio" : "video",
-                 mediaTimeUs);
-
-            reply->post();
-            return;
-        }
-
-        skipUntilMediaTimeUs = -1;
-    }
-
-    if (!audio && mCCDecoder->isSelected()) {
-        mCCDecoder->display(mediaTimeUs);
-    }
-
-    mRenderer->queueBuffer(audio, buffer, reply);
-}
-
 void NuPlayer::updateVideoSize(
         const sp<AMessage> &inputFormat,
         const sp<AMessage> &outputFormat) {
@@ -1576,12 +1370,11 @@
     driver->notifyListener(msg, ext1, ext2, in);
 }
 
-void NuPlayer::flushDecoder(
-        bool audio, bool needShutdown, const sp<AMessage> &newFormat) {
+void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
     ALOGV("[%s] flushDecoder needShutdown=%d",
           audio ? "audio" : "video", needShutdown);
 
-    const sp<Decoder> &decoder = getDecoder(audio);
+    const sp<DecoderBase> &decoder = getDecoder(audio);
     if (decoder == NULL) {
         ALOGI("flushDecoder %s without decoder present",
              audio ? "audio" : "video");
@@ -1592,8 +1385,7 @@
     ++mScanSourcesGeneration;
     mScanSourcesPending = false;
 
-    decoder->signalFlush(newFormat);
-    mRenderer->flush(audio);
+    decoder->signalFlush();
 
     FlushStatus newStatus =
         needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
@@ -1608,27 +1400,9 @@
         ALOGE_IF(mFlushingVideo != NONE,
                 "video flushDecoder() is called in state %d", mFlushingVideo);
         mFlushingVideo = newStatus;
-
-        if (mCCDecoder != NULL) {
-            mCCDecoder->flush();
-        }
     }
 }
 
-void NuPlayer::updateDecoderFormatWithoutFlush(
-        bool audio, const sp<AMessage> &format) {
-    ALOGV("[%s] updateDecoderFormatWithoutFlush", audio ? "audio" : "video");
-
-    const sp<Decoder> &decoder = getDecoder(audio);
-    if (decoder == NULL) {
-        ALOGI("updateDecoderFormatWithoutFlush %s without decoder present",
-             audio ? "audio" : "video");
-        return;
-    }
-
-    decoder->signalUpdateFormat(format);
-}
-
 void NuPlayer::queueDecoderShutdown(
         bool audio, bool video, const sp<AMessage> &reply) {
     ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video);
@@ -1661,7 +1435,7 @@
 }
 
 status_t NuPlayer::getTrackInfo(Parcel* reply) const {
-    sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, id());
+    sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, this);
     msg->setPointer("reply", reply);
 
     sp<AMessage> response;
@@ -1670,7 +1444,7 @@
 }
 
 status_t NuPlayer::getSelectedTrack(int32_t type, Parcel* reply) const {
-    sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, id());
+    sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this);
     msg->setPointer("reply", reply);
     msg->setInt32("type", type);
 
@@ -1682,10 +1456,11 @@
     return err;
 }
 
-status_t NuPlayer::selectTrack(size_t trackIndex, bool select) {
-    sp<AMessage> msg = new AMessage(kWhatSelectTrack, id());
+status_t NuPlayer::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
+    sp<AMessage> msg = new AMessage(kWhatSelectTrack, this);
     msg->setSize("trackIndex", trackIndex);
     msg->setInt32("select", select);
+    msg->setInt64("timeUs", timeUs);
 
     sp<AMessage> response;
     status_t err = msg->postAndAwaitResponse(&response);
@@ -1711,8 +1486,13 @@
 }
 
 void NuPlayer::getStats(int64_t *numFramesTotal, int64_t *numFramesDropped) {
-    *numFramesTotal = mNumFramesTotal;
-    *numFramesDropped = mNumFramesDropped;
+    sp<DecoderBase> decoder = getDecoder(false /* audio */);
+    if (decoder != NULL) {
+        decoder->getStats(numFramesTotal, numFramesDropped);
+    } else {
+        *numFramesTotal = 0;
+        *numFramesDropped = 0;
+    }
 }
 
 sp<MetaData> NuPlayer::getFileMeta() {
@@ -1720,7 +1500,7 @@
 }
 
 void NuPlayer::schedulePollDuration() {
-    sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
+    sp<AMessage> msg = new AMessage(kWhatPollDuration, this);
     msg->setInt32("generation", mPollDurationGeneration);
     msg->post();
 }
@@ -1769,15 +1549,6 @@
     mSource->seekTo(seekTimeUs);
     ++mTimedTextGeneration;
 
-    if (mDriver != NULL) {
-        sp<NuPlayerDriver> driver = mDriver.promote();
-        if (driver != NULL) {
-            if (needNotify) {
-                driver->notifySeekComplete();
-            }
-        }
-    }
-
     // everything's flushed, continue playback.
 }
 
@@ -1789,8 +1560,6 @@
         return;
     }
 
-    mTimeDiscontinuityPending = true;
-
     if (audio != FLUSH_CMD_NONE && mAudioDecoder != NULL) {
         flushDecoder(true /* audio */, (audio == FLUSH_CMD_SHUTDOWN));
     }
@@ -1865,6 +1634,42 @@
     }
 }
 
+void NuPlayer::performResumeDecoders(bool needNotify) {
+    if (needNotify) {
+        mResumePending = true;
+        if (mVideoDecoder == NULL) {
+            // if audio-only, we can notify seek complete now,
+            // as the resume operation will be relatively fast.
+            finishResume();
+        }
+    }
+
+    if (mVideoDecoder != NULL) {
+        // When there is continuous seek, MediaPlayer will cache the seek
+        // position, and send down new seek request when previous seek is
+        // complete. Let's wait for at least one video output frame before
+        // notifying seek complete, so that the video thumbnail gets updated
+        // when seekbar is dragged.
+        mVideoDecoder->signalResume(needNotify);
+    }
+
+    if (mAudioDecoder != NULL) {
+        mAudioDecoder->signalResume(false /* needNotify */);
+    }
+}
+
+void NuPlayer::finishResume() {
+    if (mResumePending) {
+        mResumePending = false;
+        if (mDriver != NULL) {
+            sp<NuPlayerDriver> driver = mDriver.promote();
+            if (driver != NULL) {
+                driver->notifySeekComplete();
+            }
+        }
+    }
+}
+
 void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
     int32_t what;
     CHECK(msg->findInt32("what", &what));
@@ -1903,6 +1708,10 @@
 
             sp<NuPlayerDriver> driver = mDriver.promote();
             if (driver != NULL) {
+                if ((flags & NuPlayer::Source::FLAG_CAN_SEEK) == 0) {
+                    driver->notifyListener(
+                            MEDIA_INFO, MEDIA_INFO_NOT_SEEKABLE, 0);
+                }
                 driver->notifyFlagsChanged(flags);
             }
 
@@ -1937,18 +1746,49 @@
             break;
         }
 
+        case Source::kWhatPauseOnBufferingStart:
+        {
+            // ignore if not playing
+            if (mStarted && !mPausedByClient) {
+                ALOGI("buffer low, pausing...");
+
+                onPause();
+            }
+            // fall-thru
+        }
+
         case Source::kWhatBufferingStart:
         {
             notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
             break;
         }
 
+        case Source::kWhatResumeOnBufferingEnd:
+        {
+            // ignore if not playing
+            if (mStarted && !mPausedByClient) {
+                ALOGI("buffer ready, resuming...");
+
+                onResume();
+            }
+            // fall-thru
+        }
+
         case Source::kWhatBufferingEnd:
         {
             notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
             break;
         }
 
+        case Source::kWhatCacheStats:
+        {
+            int32_t kbps;
+            CHECK(msg->findInt32("bandwidth", &kbps));
+
+            notifyListener(MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
+            break;
+        }
+
         case Source::kWhatSubtitleData:
         {
             sp<ABuffer> buffer;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 121f7dd..a2cb53e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -26,7 +26,7 @@
 
 struct ABuffer;
 struct AMessage;
-struct MetaData;
+class MetaData;
 struct NuPlayerDriver;
 
 struct NuPlayer : public AHandler {
@@ -51,6 +51,7 @@
             const sp<IGraphicBufferProducer> &bufferProducer);
 
     void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
+    void setPlaybackRate(float rate);
     void start();
 
     void pause();
@@ -65,14 +66,12 @@
     status_t setVideoScalingMode(int32_t mode);
     status_t getTrackInfo(Parcel* reply) const;
     status_t getSelectedTrack(int32_t type, Parcel* reply) const;
-    status_t selectTrack(size_t trackIndex, bool select);
+    status_t selectTrack(size_t trackIndex, bool select, int64_t timeUs);
     status_t getCurrentPosition(int64_t *mediaUs);
     void getStats(int64_t *mNumFramesTotal, int64_t *mNumFramesDropped);
 
     sp<MetaData> getFileMeta();
 
-    static const size_t kAggregateBufferSizeBytes;
-
 protected:
     virtual ~NuPlayer();
 
@@ -84,6 +83,7 @@
 
 private:
     struct Decoder;
+    struct DecoderBase;
     struct DecoderPassThrough;
     struct CCDecoder;
     struct GenericSource;
@@ -94,6 +94,7 @@
     struct Action;
     struct SeekAction;
     struct SetSurfaceAction;
+    struct ResumeDecoderAction;
     struct FlushDecoderAction;
     struct PostMessageAction;
     struct SimpleAction;
@@ -104,6 +105,7 @@
         kWhatSetVideoNativeWindow       = '=NaW',
         kWhatSetAudioSink               = '=AuS',
         kWhatMoreDataQueued             = 'more',
+        kWhatSetRate                    = 'setR',
         kWhatStart                      = 'strt',
         kWhatScanSources                = 'scan',
         kWhatVideoNotify                = 'vidN',
@@ -128,10 +130,9 @@
     uint32_t mSourceFlags;
     sp<NativeWindowWrapper> mNativeWindow;
     sp<MediaPlayerBase::AudioSink> mAudioSink;
-    sp<Decoder> mVideoDecoder;
-    bool mVideoIsAVC;
+    sp<DecoderBase> mVideoDecoder;
     bool mOffloadAudio;
-    sp<Decoder> mAudioDecoder;
+    sp<DecoderBase> mAudioDecoder;
     sp<CCDecoder> mCCDecoder;
     sp<Renderer> mRenderer;
     sp<ALooper> mRendererLooper;
@@ -165,32 +166,29 @@
         FLUSH_CMD_SHUTDOWN,
     };
 
-    // Once the current flush is complete this indicates whether the
-    // notion of time has changed.
-    bool mTimeDiscontinuityPending;
-
     // Status of flush responses from the decoder and renderer.
     bool mFlushComplete[2][2];
 
-    // Used by feedDecoderInputData to aggregate small buffers into
-    // one large buffer.
-    sp<ABuffer> mPendingAudioAccessUnit;
-    status_t    mPendingAudioErr;
-    sp<ABuffer> mAggregateBuffer;
-
     FlushStatus mFlushingAudio;
     FlushStatus mFlushingVideo;
 
-    int64_t mSkipRenderingAudioUntilMediaTimeUs;
-    int64_t mSkipRenderingVideoUntilMediaTimeUs;
-
-    int64_t mNumFramesTotal, mNumFramesDropped;
+    // Status of flush responses from the decoder and renderer.
+    bool mResumePending;
 
     int32_t mVideoScalingMode;
 
+    float mPlaybackRate;
     bool mStarted;
 
-    inline const sp<Decoder> &getDecoder(bool audio) {
+    // Actual pause state, either as requested by client or due to buffering.
+    bool mPaused;
+
+    // Pause state as requested by client. Note that if mPausedByClient is
+    // true, mPaused is always true; if mPausedByClient is false, mPaused could
+    // still become true, when we pause internally due to buffering.
+    bool mPausedByClient;
+
+    inline const sp<DecoderBase> &getDecoder(bool audio) {
         return audio ? mAudioDecoder : mVideoDecoder;
     }
 
@@ -201,18 +199,15 @@
         mFlushComplete[1][1] = false;
     }
 
-    void openAudioSink(const sp<AMessage> &format, bool offloadOnly);
+    void tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo);
     void closeAudioSink();
 
-    status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
+    status_t instantiateDecoder(bool audio, sp<DecoderBase> *decoder);
 
     void updateVideoSize(
             const sp<AMessage> &inputFormat,
             const sp<AMessage> &outputFormat = NULL);
 
-    status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
-    void renderBuffer(bool audio, const sp<AMessage> &msg);
-
     void notifyListener(int msg, int ext1, int ext2, const Parcel *in = NULL);
 
     void handleFlushComplete(bool audio, bool isDecoder);
@@ -220,12 +215,13 @@
 
     void onStart();
     void onResume();
+    void onPause();
 
     bool audioDecoderStillNeeded();
 
-    void flushDecoder(
-            bool audio, bool needShutdown, const sp<AMessage> &newFormat = NULL);
-    void updateDecoderFormatWithoutFlush(bool audio, const sp<AMessage> &format);
+    void flushDecoder(bool audio, bool needShutdown);
+
+    void finishResume();
 
     void postScanSources();
 
@@ -239,6 +235,7 @@
     void performReset();
     void performScanSources();
     void performSetSurface(const sp<NativeWindowWrapper> &wrapper);
+    void performResumeDecoders(bool needNotify);
 
     void onSourceNotify(const sp<AMessage> &msg);
     void onClosedCaptionNotify(const sp<AMessage> &msg);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
new file mode 100644
index 0000000..cf3e8ad
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2014 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 "NuPlayerCCDecoder"
+#include <utils/Log.h>
+#include <inttypes.h>
+
+#include "avc_utils.h"
+#include "NuPlayerCCDecoder.h"
+
+#include <media/stagefright/foundation/ABitReader.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaDefs.h>
+
+namespace android {
+
+struct CCData {
+    CCData(uint8_t type, uint8_t data1, uint8_t data2)
+        : mType(type), mData1(data1), mData2(data2) {
+    }
+    bool getChannel(size_t *channel) const {
+        if (mData1 >= 0x10 && mData1 <= 0x1f) {
+            *channel = (mData1 >= 0x18 ? 1 : 0) + (mType ? 2 : 0);
+            return true;
+        }
+        return false;
+    }
+
+    uint8_t mType;
+    uint8_t mData1;
+    uint8_t mData2;
+};
+
+static bool isNullPad(CCData *cc) {
+    return cc->mData1 < 0x10 && cc->mData2 < 0x10;
+}
+
+static void dumpBytePair(const sp<ABuffer> &ccBuf) {
+    size_t offset = 0;
+    AString out;
+
+    while (offset < ccBuf->size()) {
+        char tmp[128];
+
+        CCData *cc = (CCData *) (ccBuf->data() + offset);
+
+        if (isNullPad(cc)) {
+            // 1 null pad or XDS metadata, ignore
+            offset += sizeof(CCData);
+            continue;
+        }
+
+        if (cc->mData1 >= 0x20 && cc->mData1 <= 0x7f) {
+            // 2 basic chars
+            sprintf(tmp, "[%d]Basic: %c %c", cc->mType, cc->mData1, cc->mData2);
+        } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
+                 && cc->mData2 >= 0x30 && cc->mData2 <= 0x3f) {
+            // 1 special char
+            sprintf(tmp, "[%d]Special: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+        } else if ((cc->mData1 == 0x12 || cc->mData1 == 0x1A)
+                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
+            // 1 Spanish/French char
+            sprintf(tmp, "[%d]Spanish: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+        } else if ((cc->mData1 == 0x13 || cc->mData1 == 0x1B)
+                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
+            // 1 Portuguese/German/Danish char
+            sprintf(tmp, "[%d]German: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+        } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
+                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f){
+            // Mid-Row Codes (Table 69)
+            sprintf(tmp, "[%d]Mid-row: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+        } else if (((cc->mData1 == 0x14 || cc->mData1 == 0x1c)
+                  && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f)
+                  ||
+                   ((cc->mData1 == 0x17 || cc->mData1 == 0x1f)
+                  && cc->mData2 >= 0x21 && cc->mData2 <= 0x23)){
+            // Misc Control Codes (Table 70)
+            sprintf(tmp, "[%d]Ctrl: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+        } else if ((cc->mData1 & 0x70) == 0x10
+                && (cc->mData2 & 0x40) == 0x40
+                && ((cc->mData1 & 0x07) || !(cc->mData2 & 0x20)) ) {
+            // Preamble Address Codes (Table 71)
+            sprintf(tmp, "[%d]PAC: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+        } else {
+            sprintf(tmp, "[%d]Invalid: %02x %02x", cc->mType, cc->mData1, cc->mData2);
+        }
+
+        if (out.size() > 0) {
+            out.append(", ");
+        }
+
+        out.append(tmp);
+
+        offset += sizeof(CCData);
+    }
+
+    ALOGI("%s", out.c_str());
+}
+
+NuPlayer::CCDecoder::CCDecoder(const sp<AMessage> &notify)
+    : mNotify(notify),
+      mCurrentChannel(0),
+      mSelectedTrack(-1) {
+      for (size_t i = 0; i < sizeof(mTrackIndices)/sizeof(mTrackIndices[0]); ++i) {
+          mTrackIndices[i] = -1;
+      }
+}
+
+size_t NuPlayer::CCDecoder::getTrackCount() const {
+    return mFoundChannels.size();
+}
+
+sp<AMessage> NuPlayer::CCDecoder::getTrackInfo(size_t index) const {
+    if (!isTrackValid(index)) {
+        return NULL;
+    }
+
+    sp<AMessage> format = new AMessage();
+
+    format->setInt32("type", MEDIA_TRACK_TYPE_SUBTITLE);
+    format->setString("language", "und");
+    format->setString("mime", MEDIA_MIMETYPE_TEXT_CEA_608);
+    //CC1, field 0 channel 0
+    bool isDefaultAuto = (mFoundChannels[index] == 0);
+    format->setInt32("auto", isDefaultAuto);
+    format->setInt32("default", isDefaultAuto);
+    format->setInt32("forced", 0);
+
+    return format;
+}
+
+status_t NuPlayer::CCDecoder::selectTrack(size_t index, bool select) {
+    if (!isTrackValid(index)) {
+        return BAD_VALUE;
+    }
+
+    if (select) {
+        if (mSelectedTrack == (ssize_t)index) {
+            ALOGE("track %zu already selected", index);
+            return BAD_VALUE;
+        }
+        ALOGV("selected track %zu", index);
+        mSelectedTrack = index;
+    } else {
+        if (mSelectedTrack != (ssize_t)index) {
+            ALOGE("track %zu is not selected", index);
+            return BAD_VALUE;
+        }
+        ALOGV("unselected track %zu", index);
+        mSelectedTrack = -1;
+    }
+
+    return OK;
+}
+
+bool NuPlayer::CCDecoder::isSelected() const {
+    return mSelectedTrack >= 0 && mSelectedTrack < (int32_t) getTrackCount();
+}
+
+bool NuPlayer::CCDecoder::isTrackValid(size_t index) const {
+    return index < getTrackCount();
+}
+
+int32_t NuPlayer::CCDecoder::getTrackIndex(size_t channel) const {
+    if (channel < sizeof(mTrackIndices)/sizeof(mTrackIndices[0])) {
+        return mTrackIndices[channel];
+    }
+    return -1;
+}
+
+// returns true if a new CC track is found
+bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
+    sp<ABuffer> sei;
+    if (!accessUnit->meta()->findBuffer("sei", &sei) || sei == NULL) {
+        return false;
+    }
+
+    int64_t timeUs;
+    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
+
+    bool trackAdded = false;
+
+    const NALPosition *nal = (NALPosition *) sei->data();
+
+    for (size_t i = 0; i < sei->size() / sizeof(NALPosition); ++i, ++nal) {
+        trackAdded |= parseSEINalUnit(
+                timeUs, accessUnit->data() + nal->nalOffset, nal->nalSize);
+    }
+
+    return trackAdded;
+}
+
+// returns true if a new CC track is found
+bool NuPlayer::CCDecoder::parseSEINalUnit(
+        int64_t timeUs, const uint8_t *nalStart, size_t nalSize) {
+    unsigned nalType = nalStart[0] & 0x1f;
+
+    // the buffer should only have SEI in it
+    if (nalType != 6) {
+        return false;
+    }
+
+    bool trackAdded = false;
+    NALBitReader br(nalStart + 1, nalSize - 1);
+    // sei_message()
+    while (br.atLeastNumBitsLeft(16)) { // at least 16-bit for sei_message()
+        uint32_t payload_type = 0;
+        size_t payload_size = 0;
+        uint8_t last_byte;
+
+        do {
+            last_byte = br.getBits(8);
+            payload_type += last_byte;
+        } while (last_byte == 0xFF);
+
+        do {
+            last_byte = br.getBits(8);
+            payload_size += last_byte;
+        } while (last_byte == 0xFF);
+
+        // sei_payload()
+        if (payload_type == 4) {
+            bool isCC = false;
+            if (payload_size > 1 + 2 + 4 + 1) {
+                // user_data_registered_itu_t_t35()
+
+                // ATSC A/72: 6.4.2
+                uint8_t itu_t_t35_country_code = br.getBits(8);
+                uint16_t itu_t_t35_provider_code = br.getBits(16);
+                uint32_t user_identifier = br.getBits(32);
+                uint8_t user_data_type_code = br.getBits(8);
+
+                payload_size -= 1 + 2 + 4 + 1;
+
+                isCC = itu_t_t35_country_code == 0xB5
+                        && itu_t_t35_provider_code == 0x0031
+                        && user_identifier == 'GA94'
+                        && user_data_type_code == 0x3;
+            }
+
+            if (isCC && payload_size > 2) {
+                // MPEG_cc_data()
+                // ATSC A/53 Part 4: 6.2.3.1
+                br.skipBits(1); //process_em_data_flag
+                bool process_cc_data_flag = br.getBits(1);
+                br.skipBits(1); //additional_data_flag
+                size_t cc_count = br.getBits(5);
+                br.skipBits(8); // em_data;
+                payload_size -= 2;
+
+                if (process_cc_data_flag) {
+                    AString out;
+
+                    sp<ABuffer> ccBuf = new ABuffer(cc_count * sizeof(CCData));
+                    ccBuf->setRange(0, 0);
+
+                    for (size_t i = 0; i < cc_count && payload_size >= 3; i++) {
+                        uint8_t marker = br.getBits(5);
+                        CHECK_EQ(marker, 0x1f);
+
+                        bool cc_valid = br.getBits(1);
+                        uint8_t cc_type = br.getBits(2);
+                        // remove odd parity bit
+                        uint8_t cc_data_1 = br.getBits(8) & 0x7f;
+                        uint8_t cc_data_2 = br.getBits(8) & 0x7f;
+
+                        payload_size -= 3;
+
+                        if (cc_valid
+                                && (cc_type == 0 || cc_type == 1)) {
+                            CCData cc(cc_type, cc_data_1, cc_data_2);
+                            if (!isNullPad(&cc)) {
+                                size_t channel;
+                                if (cc.getChannel(&channel) && getTrackIndex(channel) < 0) {
+                                    mTrackIndices[channel] = mFoundChannels.size();
+                                    mFoundChannels.push_back(channel);
+                                    trackAdded = true;
+                                }
+                                memcpy(ccBuf->data() + ccBuf->size(),
+                                        (void *)&cc, sizeof(cc));
+                                ccBuf->setRange(0, ccBuf->size() + sizeof(CCData));
+                            }
+                        }
+                    }
+
+                    mCCMap.add(timeUs, ccBuf);
+                    break;
+                }
+            } else {
+                ALOGV("Malformed SEI payload type 4");
+            }
+        } else {
+            ALOGV("Unsupported SEI payload type %d", payload_type);
+        }
+
+        // skipping remaining bits of this payload
+        br.skipBits(payload_size * 8);
+    }
+
+    return trackAdded;
+}
+
+sp<ABuffer> NuPlayer::CCDecoder::filterCCBuf(
+        const sp<ABuffer> &ccBuf, size_t index) {
+    sp<ABuffer> filteredCCBuf = new ABuffer(ccBuf->size());
+    filteredCCBuf->setRange(0, 0);
+
+    size_t cc_count = ccBuf->size() / sizeof(CCData);
+    const CCData* cc_data = (const CCData*)ccBuf->data();
+    for (size_t i = 0; i < cc_count; ++i) {
+        size_t channel;
+        if (cc_data[i].getChannel(&channel)) {
+            mCurrentChannel = channel;
+        }
+        if (mCurrentChannel == mFoundChannels[index]) {
+            memcpy(filteredCCBuf->data() + filteredCCBuf->size(),
+                    (void *)&cc_data[i], sizeof(CCData));
+            filteredCCBuf->setRange(0, filteredCCBuf->size() + sizeof(CCData));
+        }
+    }
+
+    return filteredCCBuf;
+}
+
+void NuPlayer::CCDecoder::decode(const sp<ABuffer> &accessUnit) {
+    if (extractFromSEI(accessUnit)) {
+        ALOGI("Found CEA-608 track");
+        sp<AMessage> msg = mNotify->dup();
+        msg->setInt32("what", kWhatTrackAdded);
+        msg->post();
+    }
+    // TODO: extract CC from other sources
+}
+
+void NuPlayer::CCDecoder::display(int64_t timeUs) {
+    if (!isTrackValid(mSelectedTrack)) {
+        ALOGE("Could not find current track(index=%d)", mSelectedTrack);
+        return;
+    }
+
+    ssize_t index = mCCMap.indexOfKey(timeUs);
+    if (index < 0) {
+        ALOGV("cc for timestamp %" PRId64 " not found", timeUs);
+        return;
+    }
+
+    sp<ABuffer> ccBuf = filterCCBuf(mCCMap.valueAt(index), mSelectedTrack);
+
+    if (ccBuf->size() > 0) {
+#if 0
+        dumpBytePair(ccBuf);
+#endif
+
+        ccBuf->meta()->setInt32("trackIndex", mSelectedTrack);
+        ccBuf->meta()->setInt64("timeUs", timeUs);
+        ccBuf->meta()->setInt64("durationUs", 0ll);
+
+        sp<AMessage> msg = mNotify->dup();
+        msg->setInt32("what", kWhatClosedCaptionData);
+        msg->setBuffer("buffer", ccBuf);
+        msg->post();
+    }
+
+    // remove all entries before timeUs
+    mCCMap.removeItemsAt(0, index + 1);
+}
+
+void NuPlayer::CCDecoder::flush() {
+    mCCMap.clear();
+}
+
+}  // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h
new file mode 100644
index 0000000..77fb0fe
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2014 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 NUPLAYER_CCDECODER_H_
+
+#define NUPLAYER_CCDECODER_H_
+
+#include "NuPlayer.h"
+
+namespace android {
+
+struct NuPlayer::CCDecoder : public RefBase {
+    enum {
+        kWhatClosedCaptionData,
+        kWhatTrackAdded,
+    };
+
+    CCDecoder(const sp<AMessage> &notify);
+
+    size_t getTrackCount() const;
+    sp<AMessage> getTrackInfo(size_t index) const;
+    status_t selectTrack(size_t index, bool select);
+    bool isSelected() const;
+    void decode(const sp<ABuffer> &accessUnit);
+    void display(int64_t timeUs);
+    void flush();
+
+private:
+    sp<AMessage> mNotify;
+    KeyedVector<int64_t, sp<ABuffer> > mCCMap;
+    size_t mCurrentChannel;
+    int32_t mSelectedTrack;
+    int32_t mTrackIndices[4];
+    Vector<size_t> mFoundChannels;
+
+    bool isTrackValid(size_t index) const;
+    int32_t getTrackIndex(size_t channel) const;
+    bool extractFromSEI(const sp<ABuffer> &accessUnit);
+    bool parseSEINalUnit(int64_t timeUs, const uint8_t *nalStart, size_t nalSize);
+    sp<ABuffer> filterCCBuf(const sp<ABuffer> &ccBuf, size_t index);
+
+    DISALLOW_EVIL_CONSTRUCTORS(CCDecoder);
+};
+
+}  // namespace android
+
+#endif  // NUPLAYER_CCDECODER_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 27f6131..04ac699 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright 2014 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.
@@ -19,10 +19,12 @@
 #include <utils/Log.h>
 #include <inttypes.h>
 
+#include "NuPlayerCCDecoder.h"
 #include "NuPlayerDecoder.h"
+#include "NuPlayerRenderer.h"
+#include "NuPlayerSource.h"
 
 #include <media/ICrypto.h>
-#include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -31,71 +33,105 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 
+#include "avc_utils.h"
+#include "ATSParser.h"
+
 namespace android {
 
 NuPlayer::Decoder::Decoder(
         const sp<AMessage> &notify,
-        const sp<NativeWindowWrapper> &nativeWindow)
-    : mNotify(notify),
+        const sp<Source> &source,
+        const sp<Renderer> &renderer,
+        const sp<NativeWindowWrapper> &nativeWindow,
+        const sp<CCDecoder> &ccDecoder)
+    : DecoderBase(notify),
       mNativeWindow(nativeWindow),
-      mBufferGeneration(0),
+      mSource(source),
+      mRenderer(renderer),
+      mCCDecoder(ccDecoder),
+      mSkipRenderingUntilMediaTimeUs(-1ll),
+      mNumFramesTotal(0ll),
+      mNumFramesDropped(0ll),
+      mIsAudio(true),
+      mIsVideoAVC(false),
+      mIsSecure(false),
+      mFormatChangePending(false),
+      mTimeChangePending(false),
       mPaused(true),
+      mResumePending(false),
       mComponentName("decoder") {
-    // Every decoder has its own looper because MediaCodec operations
-    // are blocking, but NuPlayer needs asynchronous operations.
-    mDecoderLooper = new ALooper;
-    mDecoderLooper->setName("NPDecoder");
-    mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
-
     mCodecLooper = new ALooper;
     mCodecLooper->setName("NPDecoder-CL");
     mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
 }
 
 NuPlayer::Decoder::~Decoder() {
-    mDecoderLooper->unregisterHandler(id());
-    mDecoderLooper->stop();
-
     releaseAndResetMediaBuffers();
 }
 
-static
-status_t PostAndAwaitResponse(
-        const sp<AMessage> &msg, sp<AMessage> *response) {
-    status_t err = msg->postAndAwaitResponse(response);
-
-    if (err != OK) {
-        return err;
-    }
-
-    if (!(*response)->findInt32("err", &err)) {
-        err = OK;
-    }
-
-    return err;
+void NuPlayer::Decoder::getStats(
+        int64_t *numFramesTotal,
+        int64_t *numFramesDropped) const {
+    *numFramesTotal = mNumFramesTotal;
+    *numFramesDropped = mNumFramesDropped;
 }
 
-void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
-    mCSDsForCurrentFormat.clear();
-    for (int32_t i = 0; ; ++i) {
-        AString tag = "csd-";
-        tag.append(i);
-        sp<ABuffer> buffer;
-        if (!format->findBuffer(tag.c_str(), &buffer)) {
+void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
+    ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
+
+    switch (msg->what()) {
+        case kWhatCodecNotify:
+        {
+            if (!isStaleReply(msg)) {
+                int32_t numInput, numOutput;
+
+                if (!msg->findInt32("input-buffers", &numInput)) {
+                    numInput = INT32_MAX;
+                }
+
+                if (!msg->findInt32("output-buffers", &numOutput)) {
+                    numOutput = INT32_MAX;
+                }
+
+                if (!mPaused) {
+                    while (numInput-- > 0 && handleAnInputBuffer()) {}
+                }
+
+                while (numOutput-- > 0 && handleAnOutputBuffer()) {}
+            }
+
+            requestCodecNotification();
             break;
         }
-        mCSDsForCurrentFormat.push(buffer);
+
+        case kWhatRenderBuffer:
+        {
+            if (!isStaleReply(msg)) {
+                onRenderBuffer(msg);
+            }
+            break;
+        }
+
+        default:
+            DecoderBase::onMessageReceived(msg);
+            break;
     }
 }
 
 void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
     CHECK(mCodec == NULL);
 
+    mFormatChangePending = false;
+    mTimeChangePending = false;
+
     ++mBufferGeneration;
 
     AString mime;
     CHECK(format->findString("mime", &mime));
 
+    mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
+    mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
+
     sp<Surface> surface = NULL;
     if (mNativeWindow != NULL) {
         surface = mNativeWindow->getSurfaceTextureClient();
@@ -123,6 +159,7 @@
         handleError(UNKNOWN_ERROR);
         return;
     }
+    mIsSecure = secure;
 
     mCodec->getName(&mComponentName);
 
@@ -169,83 +206,151 @@
             mInputBuffers.size(),
             mOutputBuffers.size());
 
-    requestCodecNotification();
+    if (mRenderer != NULL) {
+        requestCodecNotification();
+    }
     mPaused = false;
+    mResumePending = false;
 }
 
-void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
-    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
-        if (mMediaBuffers[i] != NULL) {
-            mMediaBuffers[i]->release();
-            mMediaBuffers.editItemAt(i) = NULL;
-        }
+void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
+    bool hadNoRenderer = (mRenderer == NULL);
+    mRenderer = renderer;
+    if (hadNoRenderer && mRenderer != NULL) {
+        requestCodecNotification();
     }
-    mMediaBuffers.resize(mInputBuffers.size());
-    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
-        mMediaBuffers.editItemAt(i) = NULL;
-    }
-    mInputBufferIsDequeued.clear();
-    mInputBufferIsDequeued.resize(mInputBuffers.size());
-    for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
-        mInputBufferIsDequeued.editItemAt(i) = false;
-    }
-
-    mPendingInputMessages.clear();
 }
 
-void NuPlayer::Decoder::requestCodecNotification() {
+void NuPlayer::Decoder::onGetInputBuffers(
+        Vector<sp<ABuffer> > *dstBuffers) {
+    dstBuffers->clear();
+    for (size_t i = 0; i < mInputBuffers.size(); i++) {
+        dstBuffers->push(mInputBuffers[i]);
+    }
+}
+
+void NuPlayer::Decoder::onResume(bool notifyComplete) {
+    mPaused = false;
+
+    if (notifyComplete) {
+        mResumePending = true;
+    }
+}
+
+void NuPlayer::Decoder::doFlush(bool notifyComplete) {
+    if (mCCDecoder != NULL) {
+        mCCDecoder->flush();
+    }
+
+    if (mRenderer != NULL) {
+        mRenderer->flush(mIsAudio, notifyComplete);
+        mRenderer->signalTimeDiscontinuity();
+    }
+
+    status_t err = OK;
     if (mCodec != NULL) {
-        sp<AMessage> reply = new AMessage(kWhatCodecNotify, id());
-        reply->setInt32("generation", mBufferGeneration);
-        mCodec->requestActivityNotification(reply);
+        err = mCodec->flush();
+        mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
+        ++mBufferGeneration;
     }
+
+    if (err != OK) {
+        ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err);
+        handleError(err);
+        // finish with posting kWhatFlushCompleted.
+        // we attempt to release the buffers even if flush fails.
+    }
+    releaseAndResetMediaBuffers();
 }
 
-bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
-    int32_t generation;
-    CHECK(msg->findInt32("generation", &generation));
-    return generation != mBufferGeneration;
-}
+void NuPlayer::Decoder::onFlush() {
+    doFlush(true);
 
-void NuPlayer::Decoder::init() {
-    mDecoderLooper->registerHandler(this);
-}
-
-void NuPlayer::Decoder::configure(const sp<AMessage> &format) {
-    sp<AMessage> msg = new AMessage(kWhatConfigure, id());
-    msg->setMessage("format", format);
-    msg->post();
-}
-
-void NuPlayer::Decoder::signalUpdateFormat(const sp<AMessage> &format) {
-    sp<AMessage> msg = new AMessage(kWhatUpdateFormat, id());
-    msg->setMessage("format", format);
-    msg->post();
-}
-
-status_t NuPlayer::Decoder::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
-    sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, id());
-    msg->setPointer("buffers", buffers);
-
-    sp<AMessage> response;
-    return PostAndAwaitResponse(msg, &response);
-}
-
-void NuPlayer::Decoder::handleError(int32_t err)
-{
-    // We cannot immediately release the codec due to buffers still outstanding
-    // in the renderer.  We signal to the player the error so it can shutdown/release the
-    // decoder after flushing and increment the generation to discard unnecessary messages.
-
-    ++mBufferGeneration;
+    if (isDiscontinuityPending()) {
+        // This could happen if the client starts seeking/shutdown
+        // after we queued an EOS for discontinuities.
+        // We can consider discontinuity handled.
+        finishHandleDiscontinuity(false /* flushOnTimeChange */);
+    }
 
     sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatError);
-    notify->setInt32("err", err);
+    notify->setInt32("what", kWhatFlushCompleted);
     notify->post();
+    mPaused = true;
+}
+
+void NuPlayer::Decoder::onShutdown(bool notifyComplete) {
+    status_t err = OK;
+
+    // if there is a pending resume request, notify complete now
+    notifyResumeCompleteIfNecessary();
+
+    if (mCodec != NULL) {
+        err = mCodec->release();
+        mCodec = NULL;
+        ++mBufferGeneration;
+
+        if (mNativeWindow != NULL) {
+            // reconnect to surface as MediaCodec disconnected from it
+            status_t error =
+                    native_window_api_connect(
+                            mNativeWindow->getNativeWindow().get(),
+                            NATIVE_WINDOW_API_MEDIA);
+            ALOGW_IF(error != NO_ERROR,
+                    "[%s] failed to connect to native window, error=%d",
+                    mComponentName.c_str(), error);
+        }
+        mComponentName = "decoder";
+    }
+
+    releaseAndResetMediaBuffers();
+
+    if (err != OK) {
+        ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err);
+        handleError(err);
+        // finish with posting kWhatShutdownCompleted.
+    }
+
+    if (notifyComplete) {
+        sp<AMessage> notify = mNotify->dup();
+        notify->setInt32("what", kWhatShutdownCompleted);
+        notify->post();
+        mPaused = true;
+    }
+}
+
+void NuPlayer::Decoder::doRequestBuffers() {
+    if (isDiscontinuityPending()) {
+        return;
+    }
+    status_t err = OK;
+    while (err == OK && !mDequeuedInputBuffers.empty()) {
+        size_t bufferIx = *mDequeuedInputBuffers.begin();
+        sp<AMessage> msg = new AMessage();
+        msg->setSize("buffer-ix", bufferIx);
+        err = fetchInputData(msg);
+        if (err != OK && err != ERROR_END_OF_STREAM) {
+            // if EOS, need to queue EOS buffer
+            break;
+        }
+        mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin());
+
+        if (!mPendingInputMessages.empty()
+                || !onInputBufferFetched(msg)) {
+            mPendingInputMessages.push_back(msg);
+        }
+    }
+
+    if (err == -EWOULDBLOCK
+            && mSource->feedMoreTSData() == OK) {
+        scheduleRequestBuffers();
+    }
 }
 
 bool NuPlayer::Decoder::handleAnInputBuffer() {
+    if (isDiscontinuityPending()) {
+        return false;
+    }
     size_t bufferIx = -1;
     status_t res = mCodec->dequeueInputBuffer(&bufferIx);
     ALOGV("[%s] dequeued input: %d",
@@ -267,22 +372,21 @@
     }
     mInputBufferIsDequeued.editItemAt(bufferIx) = true;
 
-    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
-    reply->setSize("buffer-ix", bufferIx);
-    reply->setInt32("generation", mBufferGeneration);
-
     if (!mCSDsToSubmit.isEmpty()) {
+        sp<AMessage> msg = new AMessage();
+        msg->setSize("buffer-ix", bufferIx);
+
         sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
         ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
-        reply->setBuffer("buffer", buffer);
+        msg->setBuffer("buffer", buffer);
         mCSDsToSubmit.removeAt(0);
-        CHECK(onInputBufferFilled(reply));
+        CHECK(onInputBufferFetched(msg));
         return true;
     }
 
     while (!mPendingInputMessages.empty()) {
         sp<AMessage> msg = *mPendingInputMessages.begin();
-        if (!onInputBufferFilled(msg)) {
+        if (!onInputBufferFetched(msg)) {
             break;
         }
         mPendingInputMessages.erase(mPendingInputMessages.begin());
@@ -292,15 +396,262 @@
         return true;
     }
 
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatFillThisBuffer);
-    notify->setBuffer("buffer", mInputBuffers[bufferIx]);
-    notify->setMessage("reply", reply);
-    notify->post();
+    mDequeuedInputBuffers.push_back(bufferIx);
+
+    onRequestInputBuffers();
     return true;
 }
 
-bool android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) {
+bool NuPlayer::Decoder::handleAnOutputBuffer() {
+    size_t bufferIx = -1;
+    size_t offset;
+    size_t size;
+    int64_t timeUs;
+    uint32_t flags;
+    status_t res = mCodec->dequeueOutputBuffer(
+            &bufferIx, &offset, &size, &timeUs, &flags);
+
+    if (res != OK) {
+        ALOGV("[%s] dequeued output: %d", mComponentName.c_str(), res);
+    } else {
+        ALOGV("[%s] dequeued output: %d (time=%lld flags=%" PRIu32 ")",
+                mComponentName.c_str(), (int)bufferIx, timeUs, flags);
+    }
+
+    if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
+        res = mCodec->getOutputBuffers(&mOutputBuffers);
+        if (res != OK) {
+            ALOGE("Failed to get output buffers for %s after INFO event (err=%d)",
+                    mComponentName.c_str(), res);
+            handleError(res);
+            return false;
+        }
+        // NuPlayer ignores this
+        return true;
+    } else if (res == INFO_FORMAT_CHANGED) {
+        sp<AMessage> format = new AMessage();
+        res = mCodec->getOutputFormat(&format);
+        if (res != OK) {
+            ALOGE("Failed to get output format for %s after INFO event (err=%d)",
+                    mComponentName.c_str(), res);
+            handleError(res);
+            return false;
+        }
+
+        if (!mIsAudio) {
+            sp<AMessage> notify = mNotify->dup();
+            notify->setInt32("what", kWhatVideoSizeChanged);
+            notify->setMessage("format", format);
+            notify->post();
+        } else if (mRenderer != NULL) {
+            uint32_t flags;
+            int64_t durationUs;
+            bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
+            if (!hasVideo &&
+                    mSource->getDuration(&durationUs) == OK &&
+                    durationUs
+                        > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
+                flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+            } else {
+                flags = AUDIO_OUTPUT_FLAG_NONE;
+            }
+
+            res = mRenderer->openAudioSink(
+                    format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaded */);
+            if (res != OK) {
+                ALOGE("Failed to open AudioSink on format change for %s (err=%d)",
+                        mComponentName.c_str(), res);
+                handleError(res);
+                return false;
+            }
+        }
+        return true;
+    } else if (res == INFO_DISCONTINUITY) {
+        // nothing to do
+        return true;
+    } else if (res != OK) {
+        if (res != -EAGAIN) {
+            ALOGE("Failed to dequeue output buffer for %s (err=%d)",
+                    mComponentName.c_str(), res);
+            handleError(res);
+        }
+        return false;
+    }
+
+    CHECK_LT(bufferIx, mOutputBuffers.size());
+    sp<ABuffer> buffer = mOutputBuffers[bufferIx];
+    buffer->setRange(offset, size);
+    buffer->meta()->clear();
+    buffer->meta()->setInt64("timeUs", timeUs);
+
+    bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
+    // we do not expect CODECCONFIG or SYNCFRAME for decoder
+
+    sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this);
+    reply->setSize("buffer-ix", bufferIx);
+    reply->setInt32("generation", mBufferGeneration);
+
+    if (eos) {
+        ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video");
+
+        buffer->meta()->setInt32("eos", true);
+        reply->setInt32("eos", true);
+    } else if (mSkipRenderingUntilMediaTimeUs >= 0) {
+        if (timeUs < mSkipRenderingUntilMediaTimeUs) {
+            ALOGV("[%s] dropping buffer at time %lld as requested.",
+                     mComponentName.c_str(), (long long)timeUs);
+
+            reply->post();
+            return true;
+        }
+
+        mSkipRenderingUntilMediaTimeUs = -1;
+    }
+
+    // wait until 1st frame comes out to signal resume complete
+    notifyResumeCompleteIfNecessary();
+
+    if (mRenderer != NULL) {
+        // send the buffer to renderer.
+        mRenderer->queueBuffer(mIsAudio, buffer, reply);
+        if (eos && !isDiscontinuityPending()) {
+            mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
+        }
+    }
+
+    return true;
+}
+
+void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
+    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
+        if (mMediaBuffers[i] != NULL) {
+            mMediaBuffers[i]->release();
+            mMediaBuffers.editItemAt(i) = NULL;
+        }
+    }
+    mMediaBuffers.resize(mInputBuffers.size());
+    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
+        mMediaBuffers.editItemAt(i) = NULL;
+    }
+    mInputBufferIsDequeued.clear();
+    mInputBufferIsDequeued.resize(mInputBuffers.size());
+    for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
+        mInputBufferIsDequeued.editItemAt(i) = false;
+    }
+
+    mPendingInputMessages.clear();
+    mDequeuedInputBuffers.clear();
+    mSkipRenderingUntilMediaTimeUs = -1;
+}
+
+void NuPlayer::Decoder::requestCodecNotification() {
+    if (mCodec != NULL) {
+        sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
+        reply->setInt32("generation", mBufferGeneration);
+        mCodec->requestActivityNotification(reply);
+    }
+}
+
+bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
+    int32_t generation;
+    CHECK(msg->findInt32("generation", &generation));
+    return generation != mBufferGeneration;
+}
+
+status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) {
+    sp<ABuffer> accessUnit;
+    bool dropAccessUnit;
+    do {
+        status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
+
+        if (err == -EWOULDBLOCK) {
+            return err;
+        } else if (err != OK) {
+            if (err == INFO_DISCONTINUITY) {
+                int32_t type;
+                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
+
+                bool formatChange =
+                    (mIsAudio &&
+                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
+                    || (!mIsAudio &&
+                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
+
+                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
+
+                ALOGI("%s discontinuity (format=%d, time=%d)",
+                        mIsAudio ? "audio" : "video", formatChange, timeChange);
+
+                bool seamlessFormatChange = false;
+                sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
+                if (formatChange) {
+                    seamlessFormatChange =
+                        supportsSeamlessFormatChange(newFormat);
+                    // treat seamless format change separately
+                    formatChange = !seamlessFormatChange;
+                }
+
+                // For format or time change, return EOS to queue EOS input,
+                // then wait for EOS on output.
+                if (formatChange /* not seamless */) {
+                    mFormatChangePending = true;
+                    err = ERROR_END_OF_STREAM;
+                } else if (timeChange) {
+                    rememberCodecSpecificData(newFormat);
+                    mTimeChangePending = true;
+                    err = ERROR_END_OF_STREAM;
+                } else if (seamlessFormatChange) {
+                    // reuse existing decoder and don't flush
+                    rememberCodecSpecificData(newFormat);
+                    continue;
+                } else {
+                    // This stream is unaffected by the discontinuity
+                    return -EWOULDBLOCK;
+                }
+            }
+
+            // reply should only be returned without a buffer set
+            // when there is an error (including EOS)
+            CHECK(err != OK);
+
+            reply->setInt32("err", err);
+            return ERROR_END_OF_STREAM;
+        }
+
+        if (!mIsAudio) {
+            ++mNumFramesTotal;
+        }
+
+        dropAccessUnit = false;
+        if (!mIsAudio
+                && !mIsSecure
+                && mRenderer->getVideoLateByUs() > 100000ll
+                && mIsVideoAVC
+                && !IsAVCReferenceFrame(accessUnit)) {
+            dropAccessUnit = true;
+            ++mNumFramesDropped;
+        }
+    } while (dropAccessUnit);
+
+    // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
+#if 0
+    int64_t mediaTimeUs;
+    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
+    ALOGV("[%s] feeding input buffer at media time %" PRId64,
+         mIsAudio ? "audio" : "video",
+         mediaTimeUs / 1E6);
+#endif
+
+    if (mCCDecoder != NULL) {
+        mCCDecoder->decode(accessUnit);
+    }
+
+    reply->setBuffer("buffer", accessUnit);
+
+    return OK;
+}
+
+bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
     size_t bufferIx;
     CHECK(msg->findSize("buffer-ix", &bufferIx));
     CHECK_LT(bufferIx, mInputBuffers.size());
@@ -342,16 +693,11 @@
         }
     }
 
-
-
     if (buffer == NULL /* includes !hasBuffer */) {
         int32_t streamErr = ERROR_END_OF_STREAM;
         CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
 
-        if (streamErr == OK) {
-            /* buffers are returned to hold on to */
-            return true;
-        }
+        CHECK(streamErr != OK);
 
         // attempt to queue EOS
         status_t err = mCodec->queueInputBuffer(
@@ -375,6 +721,17 @@
             handleError(streamErr);
         }
     } else {
+        sp<AMessage> extra;
+        if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
+            int64_t resumeAtMediaTimeUs;
+            if (extra->findInt64(
+                        "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
+                ALOGI("[%s] suppressing rendering until %lld us",
+                        mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
+                mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
+            }
+        }
+
         int64_t timeUs = 0;
         uint32_t flags = 0;
         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
@@ -418,96 +775,23 @@
     return true;
 }
 
-bool NuPlayer::Decoder::handleAnOutputBuffer() {
-    size_t bufferIx = -1;
-    size_t offset;
-    size_t size;
-    int64_t timeUs;
-    uint32_t flags;
-    status_t res = mCodec->dequeueOutputBuffer(
-            &bufferIx, &offset, &size, &timeUs, &flags);
-
-    if (res != OK) {
-        ALOGV("[%s] dequeued output: %d", mComponentName.c_str(), res);
-    } else {
-        ALOGV("[%s] dequeued output: %d (time=%lld flags=%" PRIu32 ")",
-                mComponentName.c_str(), (int)bufferIx, timeUs, flags);
-    }
-
-    if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
-        res = mCodec->getOutputBuffers(&mOutputBuffers);
-        if (res != OK) {
-            ALOGE("Failed to get output buffers for %s after INFO event (err=%d)",
-                    mComponentName.c_str(), res);
-            handleError(res);
-            return false;
-        }
-        // NuPlayer ignores this
-        return true;
-    } else if (res == INFO_FORMAT_CHANGED) {
-        sp<AMessage> format = new AMessage();
-        res = mCodec->getOutputFormat(&format);
-        if (res != OK) {
-            ALOGE("Failed to get output format for %s after INFO event (err=%d)",
-                    mComponentName.c_str(), res);
-            handleError(res);
-            return false;
-        }
-
-        sp<AMessage> notify = mNotify->dup();
-        notify->setInt32("what", kWhatOutputFormatChanged);
-        notify->setMessage("format", format);
-        notify->post();
-        return true;
-    } else if (res == INFO_DISCONTINUITY) {
-        // nothing to do
-        return true;
-    } else if (res != OK) {
-        if (res != -EAGAIN) {
-            ALOGE("Failed to dequeue output buffer for %s (err=%d)",
-                    mComponentName.c_str(), res);
-            handleError(res);
-        }
-        return false;
-    }
-
-    CHECK_LT(bufferIx, mOutputBuffers.size());
-    sp<ABuffer> buffer = mOutputBuffers[bufferIx];
-    buffer->setRange(offset, size);
-    buffer->meta()->clear();
-    buffer->meta()->setInt64("timeUs", timeUs);
-    if (flags & MediaCodec::BUFFER_FLAG_EOS) {
-        buffer->meta()->setInt32("eos", true);
-    }
-    // we do not expect CODECCONFIG or SYNCFRAME for decoder
-
-    sp<AMessage> reply = new AMessage(kWhatRenderBuffer, id());
-    reply->setSize("buffer-ix", bufferIx);
-    reply->setInt32("generation", mBufferGeneration);
-
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatDrainThisBuffer);
-    notify->setBuffer("buffer", buffer);
-    notify->setMessage("reply", reply);
-    notify->post();
-
-    // FIXME: This should be handled after rendering is complete,
-    // but Renderer needs it now
-    if (flags & MediaCodec::BUFFER_FLAG_EOS) {
-        ALOGV("queueing eos [%s]", mComponentName.c_str());
-        sp<AMessage> notify = mNotify->dup();
-        notify->setInt32("what", kWhatEOS);
-        notify->setInt32("err", ERROR_END_OF_STREAM);
-        notify->post();
-    }
-    return true;
-}
-
 void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
     status_t err;
     int32_t render;
     size_t bufferIx;
+    int32_t eos;
     CHECK(msg->findSize("buffer-ix", &bufferIx));
+
+    if (!mIsAudio) {
+        int64_t timeUs;
+        sp<ABuffer> buffer = mOutputBuffers[bufferIx];
+        buffer->meta()->findInt64("timeUs", &timeUs);
+
+        if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
+            mCCDecoder->display(timeUs);
+        }
+    }
+
     if (msg->findInt32("render", &render) && render) {
         int64_t timestampNs;
         CHECK(msg->findInt64("timestampNs", &timestampNs));
@@ -520,194 +804,46 @@
                 mComponentName.c_str(), err);
         handleError(err);
     }
-}
-
-void NuPlayer::Decoder::onFlush() {
-    status_t err = OK;
-    if (mCodec != NULL) {
-        err = mCodec->flush();
-        mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
-        ++mBufferGeneration;
-    }
-
-    if (err != OK) {
-        ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err);
-        handleError(err);
-        // finish with posting kWhatFlushCompleted.
-        // we attempt to release the buffers even if flush fails.
-    }
-    releaseAndResetMediaBuffers();
-
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatFlushCompleted);
-    notify->post();
-    mPaused = true;
-}
-
-void NuPlayer::Decoder::onResume() {
-    mPaused = false;
-}
-
-void NuPlayer::Decoder::onShutdown() {
-    status_t err = OK;
-    if (mCodec != NULL) {
-        err = mCodec->release();
-        mCodec = NULL;
-        ++mBufferGeneration;
-
-        if (mNativeWindow != NULL) {
-            // reconnect to surface as MediaCodec disconnected from it
-            status_t error =
-                    native_window_api_connect(
-                            mNativeWindow->getNativeWindow().get(),
-                            NATIVE_WINDOW_API_MEDIA);
-            ALOGW_IF(error != NO_ERROR,
-                    "[%s] failed to connect to native window, error=%d",
-                    mComponentName.c_str(), error);
-        }
-        mComponentName = "decoder";
-    }
-
-    releaseAndResetMediaBuffers();
-
-    if (err != OK) {
-        ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err);
-        handleError(err);
-        // finish with posting kWhatShutdownCompleted.
-    }
-
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatShutdownCompleted);
-    notify->post();
-    mPaused = true;
-}
-
-void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
-    ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
-
-    switch (msg->what()) {
-        case kWhatConfigure:
-        {
-            sp<AMessage> format;
-            CHECK(msg->findMessage("format", &format));
-            onConfigure(format);
-            break;
-        }
-
-        case kWhatUpdateFormat:
-        {
-            sp<AMessage> format;
-            CHECK(msg->findMessage("format", &format));
-            rememberCodecSpecificData(format);
-            break;
-        }
-
-        case kWhatGetInputBuffers:
-        {
-            uint32_t replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
-
-            Vector<sp<ABuffer> > *dstBuffers;
-            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
-
-            dstBuffers->clear();
-            for (size_t i = 0; i < mInputBuffers.size(); i++) {
-                dstBuffers->push(mInputBuffers[i]);
-            }
-
-            (new AMessage)->postReply(replyID);
-            break;
-        }
-
-        case kWhatCodecNotify:
-        {
-            if (!isStaleReply(msg)) {
-                int32_t numInput, numOutput;
-
-                if (!msg->findInt32("input-buffers", &numInput)) {
-                    numInput = INT32_MAX;
-                }
-
-                if (!msg->findInt32("output-buffers", &numOutput)) {
-                    numOutput = INT32_MAX;
-                }
-
-                if (!mPaused) {
-                    while (numInput-- > 0 && handleAnInputBuffer()) {}
-                }
-
-                while (numOutput-- > 0 && handleAnOutputBuffer()) {}
-            }
-
-            requestCodecNotification();
-            break;
-        }
-
-        case kWhatInputBufferFilled:
-        {
-            if (!isStaleReply(msg)) {
-                if (!mPendingInputMessages.empty()
-                        || !onInputBufferFilled(msg)) {
-                    mPendingInputMessages.push_back(msg);
-                }
-            }
-
-            break;
-        }
-
-        case kWhatRenderBuffer:
-        {
-            if (!isStaleReply(msg)) {
-                onRenderBuffer(msg);
-            }
-            break;
-        }
-
-        case kWhatFlush:
-        {
-            sp<AMessage> format;
-            if (msg->findMessage("new-format", &format)) {
-                rememberCodecSpecificData(format);
-            }
-            onFlush();
-            break;
-        }
-
-        case kWhatResume:
-        {
-            onResume();
-            break;
-        }
-
-        case kWhatShutdown:
-        {
-            onShutdown();
-            break;
-        }
-
-        default:
-            TRESPASS();
-            break;
+    if (msg->findInt32("eos", &eos) && eos
+            && isDiscontinuityPending()) {
+        finishHandleDiscontinuity(true /* flushOnTimeChange */);
     }
 }
 
-void NuPlayer::Decoder::signalFlush(const sp<AMessage> &format) {
-    sp<AMessage> msg = new AMessage(kWhatFlush, id());
-    if (format != NULL) {
-        msg->setMessage("new-format", format);
+bool NuPlayer::Decoder::isDiscontinuityPending() const {
+    return mFormatChangePending || mTimeChangePending;
+}
+
+void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) {
+    ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d",
+            mFormatChangePending, mTimeChangePending, flushOnTimeChange);
+
+    // If we have format change, pause and wait to be killed;
+    // If we have time change only, flush and restart fetching.
+
+    if (mFormatChangePending) {
+        mPaused = true;
+    } else if (mTimeChangePending) {
+        if (flushOnTimeChange) {
+            doFlush(false /*notifyComplete*/);
+        }
+
+        // restart fetching input
+        scheduleRequestBuffers();
     }
+
+    // Notify NuPlayer to either shutdown decoder, or rescan sources
+    sp<AMessage> msg = mNotify->dup();
+    msg->setInt32("what", kWhatInputDiscontinuity);
+    msg->setInt32("formatChange", mFormatChangePending);
     msg->post();
+
+    mFormatChangePending = false;
+    mTimeChangePending = false;
 }
 
-void NuPlayer::Decoder::signalResume() {
-    (new AMessage(kWhatResume, id()))->post();
-}
-
-void NuPlayer::Decoder::initiateShutdown() {
-    (new AMessage(kWhatShutdown, id()))->post();
-}
-
-bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const {
+bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(
+        const sp<AMessage> &targetFormat) const {
     if (targetFormat == NULL) {
         return true;
     }
@@ -722,7 +858,7 @@
         const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
         for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
             int32_t oldVal, newVal;
-            if (!mOutputFormat->findInt32(keys[i], &oldVal) ||
+            if (!mInputFormat->findInt32(keys[i], &oldVal) ||
                     !targetFormat->findInt32(keys[i], &newVal) ||
                     oldVal != newVal) {
                 return false;
@@ -730,7 +866,7 @@
         }
 
         sp<ABuffer> oldBuf, newBuf;
-        if (mOutputFormat->findBuffer("csd-0", &oldBuf) &&
+        if (mInputFormat->findBuffer("csd-0", &oldBuf) &&
                 targetFormat->findBuffer("csd-0", &newBuf)) {
             if (oldBuf->size() != newBuf->size()) {
                 return false;
@@ -742,7 +878,7 @@
 }
 
 bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
-    if (mOutputFormat == NULL) {
+    if (mInputFormat == NULL) {
         return false;
     }
 
@@ -751,7 +887,7 @@
     }
 
     AString oldMime, newMime;
-    if (!mOutputFormat->findString("mime", &oldMime)
+    if (!mInputFormat->findString("mime", &oldMime)
             || !targetFormat->findString("mime", &newMime)
             || !(oldMime == newMime)) {
         return false;
@@ -772,332 +908,30 @@
     return seamless;
 }
 
-struct CCData {
-    CCData(uint8_t type, uint8_t data1, uint8_t data2)
-        : mType(type), mData1(data1), mData2(data2) {
-    }
-    bool getChannel(size_t *channel) const {
-        if (mData1 >= 0x10 && mData1 <= 0x1f) {
-            *channel = (mData1 >= 0x18 ? 1 : 0) + (mType ? 2 : 0);
-            return true;
-        }
-        return false;
-    }
-
-    uint8_t mType;
-    uint8_t mData1;
-    uint8_t mData2;
-};
-
-static bool isNullPad(CCData *cc) {
-    return cc->mData1 < 0x10 && cc->mData2 < 0x10;
-}
-
-static void dumpBytePair(const sp<ABuffer> &ccBuf) {
-    size_t offset = 0;
-    AString out;
-
-    while (offset < ccBuf->size()) {
-        char tmp[128];
-
-        CCData *cc = (CCData *) (ccBuf->data() + offset);
-
-        if (isNullPad(cc)) {
-            // 1 null pad or XDS metadata, ignore
-            offset += sizeof(CCData);
-            continue;
-        }
-
-        if (cc->mData1 >= 0x20 && cc->mData1 <= 0x7f) {
-            // 2 basic chars
-            sprintf(tmp, "[%d]Basic: %c %c", cc->mType, cc->mData1, cc->mData2);
-        } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
-                 && cc->mData2 >= 0x30 && cc->mData2 <= 0x3f) {
-            // 1 special char
-            sprintf(tmp, "[%d]Special: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else if ((cc->mData1 == 0x12 || cc->mData1 == 0x1A)
-                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
-            // 1 Spanish/French char
-            sprintf(tmp, "[%d]Spanish: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else if ((cc->mData1 == 0x13 || cc->mData1 == 0x1B)
-                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){
-            // 1 Portuguese/German/Danish char
-            sprintf(tmp, "[%d]German: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19)
-                 && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f){
-            // Mid-Row Codes (Table 69)
-            sprintf(tmp, "[%d]Mid-row: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else if (((cc->mData1 == 0x14 || cc->mData1 == 0x1c)
-                  && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f)
-                  ||
-                   ((cc->mData1 == 0x17 || cc->mData1 == 0x1f)
-                  && cc->mData2 >= 0x21 && cc->mData2 <= 0x23)){
-            // Misc Control Codes (Table 70)
-            sprintf(tmp, "[%d]Ctrl: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else if ((cc->mData1 & 0x70) == 0x10
-                && (cc->mData2 & 0x40) == 0x40
-                && ((cc->mData1 & 0x07) || !(cc->mData2 & 0x20)) ) {
-            // Preamble Address Codes (Table 71)
-            sprintf(tmp, "[%d]PAC: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        } else {
-            sprintf(tmp, "[%d]Invalid: %02x %02x", cc->mType, cc->mData1, cc->mData2);
-        }
-
-        if (out.size() > 0) {
-            out.append(", ");
-        }
-
-        out.append(tmp);
-
-        offset += sizeof(CCData);
-    }
-
-    ALOGI("%s", out.c_str());
-}
-
-NuPlayer::CCDecoder::CCDecoder(const sp<AMessage> &notify)
-    : mNotify(notify),
-      mCurrentChannel(0),
-      mSelectedTrack(-1) {
-      for (size_t i = 0; i < sizeof(mTrackIndices)/sizeof(mTrackIndices[0]); ++i) {
-          mTrackIndices[i] = -1;
-      }
-}
-
-size_t NuPlayer::CCDecoder::getTrackCount() const {
-    return mFoundChannels.size();
-}
-
-sp<AMessage> NuPlayer::CCDecoder::getTrackInfo(size_t index) const {
-    if (!isTrackValid(index)) {
-        return NULL;
-    }
-
-    sp<AMessage> format = new AMessage();
-
-    format->setInt32("type", MEDIA_TRACK_TYPE_SUBTITLE);
-    format->setString("language", "und");
-    format->setString("mime", MEDIA_MIMETYPE_TEXT_CEA_608);
-    //CC1, field 0 channel 0
-    bool isDefaultAuto = (mFoundChannels[index] == 0);
-    format->setInt32("auto", isDefaultAuto);
-    format->setInt32("default", isDefaultAuto);
-    format->setInt32("forced", 0);
-
-    return format;
-}
-
-status_t NuPlayer::CCDecoder::selectTrack(size_t index, bool select) {
-    if (!isTrackValid(index)) {
-        return BAD_VALUE;
-    }
-
-    if (select) {
-        if (mSelectedTrack == (ssize_t)index) {
-            ALOGE("track %zu already selected", index);
-            return BAD_VALUE;
-        }
-        ALOGV("selected track %zu", index);
-        mSelectedTrack = index;
-    } else {
-        if (mSelectedTrack != (ssize_t)index) {
-            ALOGE("track %zu is not selected", index);
-            return BAD_VALUE;
-        }
-        ALOGV("unselected track %zu", index);
-        mSelectedTrack = -1;
-    }
-
-    return OK;
-}
-
-bool NuPlayer::CCDecoder::isSelected() const {
-    return mSelectedTrack >= 0 && mSelectedTrack < (int32_t) getTrackCount();
-}
-
-bool NuPlayer::CCDecoder::isTrackValid(size_t index) const {
-    return index < getTrackCount();
-}
-
-int32_t NuPlayer::CCDecoder::getTrackIndex(size_t channel) const {
-    if (channel < sizeof(mTrackIndices)/sizeof(mTrackIndices[0])) {
-        return mTrackIndices[channel];
-    }
-    return -1;
-}
-
-// returns true if a new CC track is found
-bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
-    int64_t timeUs;
-    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
-
-    sp<ABuffer> sei;
-    if (!accessUnit->meta()->findBuffer("sei", &sei) || sei == NULL) {
-        return false;
-    }
-
-    bool trackAdded = false;
-
-    NALBitReader br(sei->data() + 1, sei->size() - 1);
-    // sei_message()
-    while (br.atLeastNumBitsLeft(16)) { // at least 16-bit for sei_message()
-        uint32_t payload_type = 0;
-        size_t payload_size = 0;
-        uint8_t last_byte;
-
-        do {
-            last_byte = br.getBits(8);
-            payload_type += last_byte;
-        } while (last_byte == 0xFF);
-
-        do {
-            last_byte = br.getBits(8);
-            payload_size += last_byte;
-        } while (last_byte == 0xFF);
-
-        // sei_payload()
-        if (payload_type == 4) {
-            // user_data_registered_itu_t_t35()
-
-            // ATSC A/72: 6.4.2
-            uint8_t itu_t_t35_country_code = br.getBits(8);
-            uint16_t itu_t_t35_provider_code = br.getBits(16);
-            uint32_t user_identifier = br.getBits(32);
-            uint8_t user_data_type_code = br.getBits(8);
-
-            payload_size -= 1 + 2 + 4 + 1;
-
-            if (itu_t_t35_country_code == 0xB5
-                    && itu_t_t35_provider_code == 0x0031
-                    && user_identifier == 'GA94'
-                    && user_data_type_code == 0x3) {
-                // MPEG_cc_data()
-                // ATSC A/53 Part 4: 6.2.3.1
-                br.skipBits(1); //process_em_data_flag
-                bool process_cc_data_flag = br.getBits(1);
-                br.skipBits(1); //additional_data_flag
-                size_t cc_count = br.getBits(5);
-                br.skipBits(8); // em_data;
-                payload_size -= 2;
-
-                if (process_cc_data_flag) {
-                    AString out;
-
-                    sp<ABuffer> ccBuf = new ABuffer(cc_count * sizeof(CCData));
-                    ccBuf->setRange(0, 0);
-
-                    for (size_t i = 0; i < cc_count; i++) {
-                        uint8_t marker = br.getBits(5);
-                        CHECK_EQ(marker, 0x1f);
-
-                        bool cc_valid = br.getBits(1);
-                        uint8_t cc_type = br.getBits(2);
-                        // remove odd parity bit
-                        uint8_t cc_data_1 = br.getBits(8) & 0x7f;
-                        uint8_t cc_data_2 = br.getBits(8) & 0x7f;
-
-                        if (cc_valid
-                                && (cc_type == 0 || cc_type == 1)) {
-                            CCData cc(cc_type, cc_data_1, cc_data_2);
-                            if (!isNullPad(&cc)) {
-                                size_t channel;
-                                if (cc.getChannel(&channel) && getTrackIndex(channel) < 0) {
-                                    mTrackIndices[channel] = mFoundChannels.size();
-                                    mFoundChannels.push_back(channel);
-                                    trackAdded = true;
-                                }
-                                memcpy(ccBuf->data() + ccBuf->size(),
-                                        (void *)&cc, sizeof(cc));
-                                ccBuf->setRange(0, ccBuf->size() + sizeof(CCData));
-                            }
-                        }
-                    }
-                    payload_size -= cc_count * 3;
-
-                    mCCMap.add(timeUs, ccBuf);
-                    break;
-                }
-            } else {
-                ALOGV("Malformed SEI payload type 4");
-            }
-        } else {
-            ALOGV("Unsupported SEI payload type %d", payload_type);
-        }
-
-        // skipping remaining bits of this payload
-        br.skipBits(payload_size * 8);
-    }
-
-    return trackAdded;
-}
-
-sp<ABuffer> NuPlayer::CCDecoder::filterCCBuf(
-        const sp<ABuffer> &ccBuf, size_t index) {
-    sp<ABuffer> filteredCCBuf = new ABuffer(ccBuf->size());
-    filteredCCBuf->setRange(0, 0);
-
-    size_t cc_count = ccBuf->size() / sizeof(CCData);
-    const CCData* cc_data = (const CCData*)ccBuf->data();
-    for (size_t i = 0; i < cc_count; ++i) {
-        size_t channel;
-        if (cc_data[i].getChannel(&channel)) {
-            mCurrentChannel = channel;
-        }
-        if (mCurrentChannel == mFoundChannels[index]) {
-            memcpy(filteredCCBuf->data() + filteredCCBuf->size(),
-                    (void *)&cc_data[i], sizeof(CCData));
-            filteredCCBuf->setRange(0, filteredCCBuf->size() + sizeof(CCData));
-        }
-    }
-
-    return filteredCCBuf;
-}
-
-void NuPlayer::CCDecoder::decode(const sp<ABuffer> &accessUnit) {
-    if (extractFromSEI(accessUnit)) {
-        ALOGI("Found CEA-608 track");
-        sp<AMessage> msg = mNotify->dup();
-        msg->setInt32("what", kWhatTrackAdded);
-        msg->post();
-    }
-    // TODO: extract CC from other sources
-}
-
-void NuPlayer::CCDecoder::display(int64_t timeUs) {
-    if (!isTrackValid(mSelectedTrack)) {
-        ALOGE("Could not find current track(index=%d)", mSelectedTrack);
+void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
+    if (format == NULL) {
         return;
     }
-
-    ssize_t index = mCCMap.indexOfKey(timeUs);
-    if (index < 0) {
-        ALOGV("cc for timestamp %" PRId64 " not found", timeUs);
-        return;
+    mCSDsForCurrentFormat.clear();
+    for (int32_t i = 0; ; ++i) {
+        AString tag = "csd-";
+        tag.append(i);
+        sp<ABuffer> buffer;
+        if (!format->findBuffer(tag.c_str(), &buffer)) {
+            break;
+        }
+        mCSDsForCurrentFormat.push(buffer);
     }
-
-    sp<ABuffer> ccBuf = filterCCBuf(mCCMap.valueAt(index), mSelectedTrack);
-
-    if (ccBuf->size() > 0) {
-#if 0
-        dumpBytePair(ccBuf);
-#endif
-
-        ccBuf->meta()->setInt32("trackIndex", mSelectedTrack);
-        ccBuf->meta()->setInt64("timeUs", timeUs);
-        ccBuf->meta()->setInt64("durationUs", 0ll);
-
-        sp<AMessage> msg = mNotify->dup();
-        msg->setInt32("what", kWhatClosedCaptionData);
-        msg->setBuffer("buffer", ccBuf);
-        msg->post();
-    }
-
-    // remove all entries before timeUs
-    mCCMap.removeItemsAt(0, index + 1);
 }
 
-void NuPlayer::CCDecoder::flush() {
-    mCCMap.clear();
+void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() {
+    if (mResumePending) {
+        mResumePending = false;
+
+        sp<AMessage> notify = mNotify->dup();
+        notify->setInt32("what", kWhatResumeCompleted);
+        notify->post();
+    }
 }
 
 }  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index dba3eee..4aab2c6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright 2014 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.
@@ -15,70 +15,54 @@
  */
 
 #ifndef NUPLAYER_DECODER_H_
-
 #define NUPLAYER_DECODER_H_
 
 #include "NuPlayer.h"
 
-#include <media/stagefright/foundation/AHandler.h>
+#include "NuPlayerDecoderBase.h"
 
 namespace android {
 
-struct ABuffer;
-struct MediaCodec;
-struct MediaBuffer;
-
-struct NuPlayer::Decoder : public AHandler {
+struct NuPlayer::Decoder : public DecoderBase {
     Decoder(const sp<AMessage> &notify,
-            const sp<NativeWindowWrapper> &nativeWindow = NULL);
+            const sp<Source> &source,
+            const sp<Renderer> &renderer = NULL,
+            const sp<NativeWindowWrapper> &nativeWindow = NULL,
+            const sp<CCDecoder> &ccDecoder = NULL);
 
-    virtual void configure(const sp<AMessage> &format);
-    virtual void init();
-
-    status_t getInputBuffers(Vector<sp<ABuffer> > *dstBuffers) const;
-    virtual void signalFlush(const sp<AMessage> &format = NULL);
-    virtual void signalUpdateFormat(const sp<AMessage> &format);
-    virtual void signalResume();
-    virtual void initiateShutdown();
-
-    virtual bool supportsSeamlessFormatChange(const sp<AMessage> &to) const;
-
-    enum {
-        kWhatFillThisBuffer      = 'flTB',
-        kWhatDrainThisBuffer     = 'drTB',
-        kWhatOutputFormatChanged = 'fmtC',
-        kWhatFlushCompleted      = 'flsC',
-        kWhatShutdownCompleted   = 'shDC',
-        kWhatEOS                 = 'eos ',
-        kWhatError               = 'err ',
-    };
+    virtual void getStats(
+            int64_t *mNumFramesTotal,
+            int64_t *mNumFramesDropped) const;
 
 protected:
-
     virtual ~Decoder();
 
     virtual void onMessageReceived(const sp<AMessage> &msg);
 
+    virtual void onConfigure(const sp<AMessage> &format);
+    virtual void onSetRenderer(const sp<Renderer> &renderer);
+    virtual void onGetInputBuffers(Vector<sp<ABuffer> > *dstBuffers);
+    virtual void onResume(bool notifyComplete);
+    virtual void onFlush();
+    virtual void onShutdown(bool notifyComplete);
+    virtual void doRequestBuffers();
+
 private:
     enum {
-        kWhatCodecNotify        = 'cdcN',
-        kWhatConfigure          = 'conf',
-        kWhatGetInputBuffers    = 'gInB',
-        kWhatInputBufferFilled  = 'inpF',
-        kWhatRenderBuffer       = 'rndr',
-        kWhatFlush              = 'flus',
-        kWhatShutdown           = 'shuD',
-        kWhatUpdateFormat       = 'uFmt',
+        kWhatCodecNotify         = 'cdcN',
+        kWhatRenderBuffer        = 'rndr',
     };
 
-    sp<AMessage> mNotify;
     sp<NativeWindowWrapper> mNativeWindow;
 
+    sp<Source> mSource;
+    sp<Renderer> mRenderer;
+    sp<CCDecoder> mCCDecoder;
+
     sp<AMessage> mInputFormat;
     sp<AMessage> mOutputFormat;
     sp<MediaCodec> mCodec;
     sp<ALooper> mCodecLooper;
-    sp<ALooper> mDecoderLooper;
 
     List<sp<AMessage> > mPendingInputMessages;
 
@@ -88,8 +72,21 @@
     Vector<sp<ABuffer> > mCSDsToSubmit;
     Vector<bool> mInputBufferIsDequeued;
     Vector<MediaBuffer *> mMediaBuffers;
+    Vector<size_t> mDequeuedInputBuffers;
 
-    void handleError(int32_t err);
+    int64_t mSkipRenderingUntilMediaTimeUs;
+    int64_t mNumFramesTotal;
+    int64_t mNumFramesDropped;
+    bool mIsAudio;
+    bool mIsVideoAVC;
+    bool mIsSecure;
+    bool mFormatChangePending;
+    bool mTimeChangePending;
+
+    bool mPaused;
+    bool mResumePending;
+    AString mComponentName;
+
     bool handleAnInputBuffer();
     bool handleAnOutputBuffer();
 
@@ -97,55 +94,22 @@
     void requestCodecNotification();
     bool isStaleReply(const sp<AMessage> &msg);
 
-    void onConfigure(const sp<AMessage> &format);
-    void onFlush();
-    void onResume();
-    bool onInputBufferFilled(const sp<AMessage> &msg);
+    void doFlush(bool notifyComplete);
+    status_t fetchInputData(sp<AMessage> &reply);
+    bool onInputBufferFetched(const sp<AMessage> &msg);
     void onRenderBuffer(const sp<AMessage> &msg);
-    void onShutdown();
 
-    int32_t mBufferGeneration;
-    bool mPaused;
-    AString mComponentName;
-
+    bool supportsSeamlessFormatChange(const sp<AMessage> &to) const;
     bool supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const;
     void rememberCodecSpecificData(const sp<AMessage> &format);
+    bool isDiscontinuityPending() const;
+    void finishHandleDiscontinuity(bool flushOnTimeChange);
+
+    void notifyResumeCompleteIfNecessary();
 
     DISALLOW_EVIL_CONSTRUCTORS(Decoder);
 };
 
-struct NuPlayer::CCDecoder : public RefBase {
-    enum {
-        kWhatClosedCaptionData,
-        kWhatTrackAdded,
-    };
-
-    CCDecoder(const sp<AMessage> &notify);
-
-    size_t getTrackCount() const;
-    sp<AMessage> getTrackInfo(size_t index) const;
-    status_t selectTrack(size_t index, bool select);
-    bool isSelected() const;
-    void decode(const sp<ABuffer> &accessUnit);
-    void display(int64_t timeUs);
-    void flush();
-
-private:
-    sp<AMessage> mNotify;
-    KeyedVector<int64_t, sp<ABuffer> > mCCMap;
-    size_t mCurrentChannel;
-    int32_t mSelectedTrack;
-    int32_t mTrackIndices[4];
-    Vector<size_t> mFoundChannels;
-
-    bool isTrackValid(size_t index) const;
-    int32_t getTrackIndex(size_t channel) const;
-    bool extractFromSEI(const sp<ABuffer> &accessUnit);
-    sp<ABuffer> filterCCBuf(const sp<ABuffer> &ccBuf, size_t index);
-
-    DISALLOW_EVIL_CONSTRUCTORS(CCDecoder);
-};
-
 }  // namespace android
 
 #endif  // NUPLAYER_DECODER_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
new file mode 100644
index 0000000..4636f0a
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2010 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 "NuPlayerDecoderBase"
+#include <utils/Log.h>
+#include <inttypes.h>
+
+#include "NuPlayerDecoderBase.h"
+
+#include "NuPlayerRenderer.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+namespace android {
+
+NuPlayer::DecoderBase::DecoderBase(const sp<AMessage> &notify)
+    :  mNotify(notify),
+       mBufferGeneration(0),
+       mRequestInputBuffersPending(false) {
+    // Every decoder has its own looper because MediaCodec operations
+    // are blocking, but NuPlayer needs asynchronous operations.
+    mDecoderLooper = new ALooper;
+    mDecoderLooper->setName("NPDecoder");
+    mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
+}
+
+NuPlayer::DecoderBase::~DecoderBase() {
+    mDecoderLooper->unregisterHandler(id());
+    mDecoderLooper->stop();
+}
+
+static
+status_t PostAndAwaitResponse(
+        const sp<AMessage> &msg, sp<AMessage> *response) {
+    status_t err = msg->postAndAwaitResponse(response);
+
+    if (err != OK) {
+        return err;
+    }
+
+    if (!(*response)->findInt32("err", &err)) {
+        err = OK;
+    }
+
+    return err;
+}
+
+void NuPlayer::DecoderBase::configure(const sp<AMessage> &format) {
+    sp<AMessage> msg = new AMessage(kWhatConfigure, this);
+    msg->setMessage("format", format);
+    msg->post();
+}
+
+void NuPlayer::DecoderBase::init() {
+    mDecoderLooper->registerHandler(this);
+}
+
+void NuPlayer::DecoderBase::setRenderer(const sp<Renderer> &renderer) {
+    sp<AMessage> msg = new AMessage(kWhatSetRenderer, this);
+    msg->setObject("renderer", renderer);
+    msg->post();
+}
+
+status_t NuPlayer::DecoderBase::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
+    sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, this);
+    msg->setPointer("buffers", buffers);
+
+    sp<AMessage> response;
+    return PostAndAwaitResponse(msg, &response);
+}
+
+void NuPlayer::DecoderBase::signalFlush() {
+    (new AMessage(kWhatFlush, this))->post();
+}
+
+void NuPlayer::DecoderBase::signalResume(bool notifyComplete) {
+    sp<AMessage> msg = new AMessage(kWhatResume, this);
+    msg->setInt32("notifyComplete", notifyComplete);
+    msg->post();
+}
+
+void NuPlayer::DecoderBase::initiateShutdown() {
+    (new AMessage(kWhatShutdown, this))->post();
+}
+
+void NuPlayer::DecoderBase::onRequestInputBuffers() {
+    if (mRequestInputBuffersPending) {
+        return;
+    }
+
+    doRequestBuffers();
+}
+
+void NuPlayer::DecoderBase::scheduleRequestBuffers() {
+    if (mRequestInputBuffersPending) {
+        return;
+    }
+    mRequestInputBuffersPending = true;
+    sp<AMessage> msg = new AMessage(kWhatRequestInputBuffers, this);
+    msg->post(10 * 1000ll);
+}
+
+void NuPlayer::DecoderBase::onMessageReceived(const sp<AMessage> &msg) {
+
+    switch (msg->what()) {
+        case kWhatConfigure:
+        {
+            sp<AMessage> format;
+            CHECK(msg->findMessage("format", &format));
+            onConfigure(format);
+            break;
+        }
+
+        case kWhatSetRenderer:
+        {
+            sp<RefBase> obj;
+            CHECK(msg->findObject("renderer", &obj));
+            onSetRenderer(static_cast<Renderer *>(obj.get()));
+            break;
+        }
+
+        case kWhatGetInputBuffers:
+        {
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
+            Vector<sp<ABuffer> > *dstBuffers;
+            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
+
+            onGetInputBuffers(dstBuffers);
+
+            (new AMessage)->postReply(replyID);
+            break;
+        }
+
+        case kWhatRequestInputBuffers:
+        {
+            mRequestInputBuffersPending = false;
+            onRequestInputBuffers();
+            break;
+        }
+
+        case kWhatFlush:
+        {
+            onFlush();
+            break;
+        }
+
+        case kWhatResume:
+        {
+            int32_t notifyComplete;
+            CHECK(msg->findInt32("notifyComplete", &notifyComplete));
+
+            onResume(notifyComplete);
+            break;
+        }
+
+        case kWhatShutdown:
+        {
+            onShutdown(true);
+            break;
+        }
+
+        default:
+            TRESPASS();
+            break;
+    }
+}
+
+void NuPlayer::DecoderBase::handleError(int32_t err)
+{
+    // We cannot immediately release the codec due to buffers still outstanding
+    // in the renderer.  We signal to the player the error so it can shutdown/release the
+    // decoder after flushing and increment the generation to discard unnecessary messages.
+
+    ++mBufferGeneration;
+
+    sp<AMessage> notify = mNotify->dup();
+    notify->setInt32("what", kWhatError);
+    notify->setInt32("err", err);
+    notify->post();
+}
+
+}  // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
new file mode 100644
index 0000000..97e9269
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 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 NUPLAYER_DECODER_BASE_H_
+
+#define NUPLAYER_DECODER_BASE_H_
+
+#include "NuPlayer.h"
+
+#include <media/stagefright/foundation/AHandler.h>
+
+namespace android {
+
+struct ABuffer;
+struct MediaCodec;
+struct MediaBuffer;
+
+struct NuPlayer::DecoderBase : public AHandler {
+    DecoderBase(const sp<AMessage> &notify);
+
+    void configure(const sp<AMessage> &format);
+    void init();
+
+    void setRenderer(const sp<Renderer> &renderer);
+
+    status_t getInputBuffers(Vector<sp<ABuffer> > *dstBuffers) const;
+    void signalFlush();
+    void signalResume(bool notifyComplete);
+    void initiateShutdown();
+
+    virtual void getStats(
+            int64_t *mNumFramesTotal,
+            int64_t *mNumFramesDropped) const = 0;
+
+    enum {
+        kWhatInputDiscontinuity  = 'inDi',
+        kWhatVideoSizeChanged    = 'viSC',
+        kWhatFlushCompleted      = 'flsC',
+        kWhatShutdownCompleted   = 'shDC',
+        kWhatResumeCompleted     = 'resC',
+        kWhatEOS                 = 'eos ',
+        kWhatError               = 'err ',
+    };
+
+protected:
+
+    virtual ~DecoderBase();
+
+    virtual void onMessageReceived(const sp<AMessage> &msg);
+
+    virtual void onConfigure(const sp<AMessage> &format) = 0;
+    virtual void onSetRenderer(const sp<Renderer> &renderer) = 0;
+    virtual void onGetInputBuffers(Vector<sp<ABuffer> > *dstBuffers) = 0;
+    virtual void onResume(bool notifyComplete) = 0;
+    virtual void onFlush() = 0;
+    virtual void onShutdown(bool notifyComplete) = 0;
+
+    void onRequestInputBuffers();
+    void scheduleRequestBuffers();
+    virtual void doRequestBuffers() = 0;
+    virtual void handleError(int32_t err);
+
+    sp<AMessage> mNotify;
+    int32_t mBufferGeneration;
+
+private:
+    enum {
+        kWhatConfigure           = 'conf',
+        kWhatSetRenderer         = 'setR',
+        kWhatGetInputBuffers     = 'gInB',
+        kWhatRequestInputBuffers = 'reqB',
+        kWhatFlush               = 'flus',
+        kWhatShutdown            = 'shuD',
+    };
+
+    sp<ALooper> mDecoderLooper;
+    bool mRequestInputBuffersPending;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DecoderBase);
+};
+
+}  // namespace android
+
+#endif  // NUPLAYER_DECODER_BASE_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index f7aacdd..29b4c26 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -21,79 +21,80 @@
 
 #include "NuPlayerDecoderPassThrough.h"
 
+#include "NuPlayerRenderer.h"
+#include "NuPlayerSource.h"
+
 #include <media/ICrypto.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 
+#include "ATSParser.h"
+
 namespace android {
 
+// TODO optimize buffer size for power consumption
+// The offload read buffer size is 32 KB but 24 KB uses less power.
+static const size_t kAggregateBufferSizeBytes = 24 * 1024;
 static const size_t kMaxCachedBytes = 200000;
-// The buffers will contain a bit less than kAggregateBufferSizeBytes.
-// So we can start off with just enough buffers to keep the cache full.
-static const size_t kMaxPendingBuffers = 1 + (kMaxCachedBytes / NuPlayer::kAggregateBufferSizeBytes);
 
 NuPlayer::DecoderPassThrough::DecoderPassThrough(
-        const sp<AMessage> &notify)
-    : Decoder(notify),
-      mNotify(notify),
-      mBufferGeneration(0),
+        const sp<AMessage> &notify,
+        const sp<Source> &source,
+        const sp<Renderer> &renderer)
+    : DecoderBase(notify),
+      mSource(source),
+      mRenderer(renderer),
+      mSkipRenderingUntilMediaTimeUs(-1ll),
+      mPaused(false),
       mReachedEOS(true),
-      mPendingBuffersToFill(0),
+      mPendingAudioErr(OK),
       mPendingBuffersToDrain(0),
       mCachedBytes(0),
       mComponentName("pass through decoder") {
-    mDecoderLooper = new ALooper;
-    mDecoderLooper->setName("NuPlayerDecoderPassThrough");
-    mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
+    ALOGW_IF(renderer == NULL, "expect a non-NULL renderer");
 }
 
 NuPlayer::DecoderPassThrough::~DecoderPassThrough() {
 }
 
-void NuPlayer::DecoderPassThrough::configure(const sp<AMessage> &format) {
-    sp<AMessage> msg = new AMessage(kWhatConfigure, id());
-    msg->setMessage("format", format);
-    msg->post();
-}
-
-void NuPlayer::DecoderPassThrough::init() {
-    mDecoderLooper->registerHandler(this);
-}
-
-void NuPlayer::DecoderPassThrough::signalFlush() {
-    (new AMessage(kWhatFlush, id()))->post();
-}
-
-void NuPlayer::DecoderPassThrough::signalResume() {
-    (new AMessage(kWhatResume, id()))->post();
-}
-
-void NuPlayer::DecoderPassThrough::initiateShutdown() {
-    (new AMessage(kWhatShutdown, id()))->post();
-}
-
-bool NuPlayer::DecoderPassThrough::supportsSeamlessFormatChange(
-        const sp<AMessage> & /* targetFormat */) const {
-    return true;
+void NuPlayer::DecoderPassThrough::getStats(
+        int64_t *numFramesTotal, int64_t *numFramesDropped) const {
+    *numFramesTotal = 0;
+    *numFramesDropped = 0;
 }
 
 void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) {
     ALOGV("[%s] onConfigure", mComponentName.c_str());
     mCachedBytes = 0;
-    mPendingBuffersToFill = 0;
     mPendingBuffersToDrain = 0;
     mReachedEOS = false;
     ++mBufferGeneration;
 
-    requestMaxBuffers();
+    onRequestInputBuffers();
 
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatOutputFormatChanged);
-    notify->setMessage("format", format);
-    notify->post();
+    // The audio sink is already opened before the PassThrough decoder is created.
+    // Opening again might be relevant if decoder is instantiated after shutdown and
+    // format is different.
+    status_t err = mRenderer->openAudioSink(
+            format, true /* offloadOnly */, false /* hasVideo */,
+            AUDIO_OUTPUT_FLAG_NONE /* flags */, NULL /* isOffloaded */);
+    if (err != OK) {
+        handleError(err);
+    }
+}
+
+void NuPlayer::DecoderPassThrough::onSetRenderer(
+        const sp<Renderer> &renderer) {
+    // renderer can't be changed during offloading
+    ALOGW_IF(renderer != mRenderer,
+            "ignoring request to change renderer");
+}
+
+void NuPlayer::DecoderPassThrough::onGetInputBuffers(
+        Vector<sp<ABuffer> > * /* dstBuffers */) {
+    ALOGE("onGetInputBuffers() called unexpectedly");
 }
 
 bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) {
@@ -102,100 +103,304 @@
     return generation != mBufferGeneration;
 }
 
-bool NuPlayer::DecoderPassThrough::requestABuffer() {
-    if (mCachedBytes >= kMaxCachedBytes) {
-        ALOGV("[%s] mCachedBytes = %zu",
-                mComponentName.c_str(), mCachedBytes);
-        return false;
-    }
-    if (mReachedEOS) {
-        ALOGV("[%s] reached EOS", mComponentName.c_str());
-        return false;
-    }
+bool NuPlayer::DecoderPassThrough::isDoneFetching() const {
+    ALOGV("[%s] mCachedBytes = %zu, mReachedEOS = %d mPaused = %d",
+            mComponentName.c_str(), mCachedBytes, mReachedEOS, mPaused);
 
-    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
-    reply->setInt32("generation", mBufferGeneration);
-
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatFillThisBuffer);
-    notify->setMessage("reply", reply);
-    notify->post();
-    mPendingBuffersToFill++;
-    ALOGV("requestABuffer: #ToFill = %zu, #ToDrain = %zu", mPendingBuffersToFill,
-            mPendingBuffersToDrain);
-
-    return true;
+    return mCachedBytes >= kMaxCachedBytes || mReachedEOS || mPaused;
 }
 
-void android::NuPlayer::DecoderPassThrough::onInputBufferFilled(
+void NuPlayer::DecoderPassThrough::doRequestBuffers() {
+    status_t err = OK;
+    while (!isDoneFetching()) {
+        sp<AMessage> msg = new AMessage();
+
+        err = fetchInputData(msg);
+        if (err != OK) {
+            break;
+        }
+
+        onInputBufferFetched(msg);
+    }
+
+    if (err == -EWOULDBLOCK
+            && mSource->feedMoreTSData() == OK) {
+        scheduleRequestBuffers();
+    }
+}
+
+status_t NuPlayer::DecoderPassThrough::dequeueAccessUnit(sp<ABuffer> *accessUnit) {
+    status_t err;
+
+    // Did we save an accessUnit earlier because of a discontinuity?
+    if (mPendingAudioAccessUnit != NULL) {
+        *accessUnit = mPendingAudioAccessUnit;
+        mPendingAudioAccessUnit.clear();
+        err = mPendingAudioErr;
+        ALOGV("feedDecoderInputData() use mPendingAudioAccessUnit");
+    } else {
+        err = mSource->dequeueAccessUnit(true /* audio */, accessUnit);
+    }
+
+    if (err == INFO_DISCONTINUITY || err == ERROR_END_OF_STREAM) {
+        if (mAggregateBuffer != NULL) {
+            // We already have some data so save this for later.
+            mPendingAudioErr = err;
+            mPendingAudioAccessUnit = *accessUnit;
+            (*accessUnit).clear();
+            ALOGD("return aggregated buffer and save err(=%d) for later", err);
+            err = OK;
+        }
+    }
+
+    return err;
+}
+
+sp<ABuffer> NuPlayer::DecoderPassThrough::aggregateBuffer(
+        const sp<ABuffer> &accessUnit) {
+    sp<ABuffer> aggregate;
+
+    if (accessUnit == NULL) {
+        // accessUnit is saved to mPendingAudioAccessUnit
+        // return current mAggregateBuffer
+        aggregate = mAggregateBuffer;
+        mAggregateBuffer.clear();
+        return aggregate;
+    }
+
+    size_t smallSize = accessUnit->size();
+    if ((mAggregateBuffer == NULL)
+            // Don't bother if only room for a few small buffers.
+            && (smallSize < (kAggregateBufferSizeBytes / 3))) {
+        // Create a larger buffer for combining smaller buffers from the extractor.
+        mAggregateBuffer = new ABuffer(kAggregateBufferSizeBytes);
+        mAggregateBuffer->setRange(0, 0); // start empty
+    }
+
+    if (mAggregateBuffer != NULL) {
+        int64_t timeUs;
+        int64_t dummy;
+        bool smallTimestampValid = accessUnit->meta()->findInt64("timeUs", &timeUs);
+        bool bigTimestampValid = mAggregateBuffer->meta()->findInt64("timeUs", &dummy);
+        // Will the smaller buffer fit?
+        size_t bigSize = mAggregateBuffer->size();
+        size_t roomLeft = mAggregateBuffer->capacity() - bigSize;
+        // Should we save this small buffer for the next big buffer?
+        // If the first small buffer did not have a timestamp then save
+        // any buffer that does have a timestamp until the next big buffer.
+        if ((smallSize > roomLeft)
+            || (!bigTimestampValid && (bigSize > 0) && smallTimestampValid)) {
+            mPendingAudioErr = OK;
+            mPendingAudioAccessUnit = accessUnit;
+            aggregate = mAggregateBuffer;
+            mAggregateBuffer.clear();
+        } else {
+            // Grab time from first small buffer if available.
+            if ((bigSize == 0) && smallTimestampValid) {
+                mAggregateBuffer->meta()->setInt64("timeUs", timeUs);
+            }
+            // Append small buffer to the bigger buffer.
+            memcpy(mAggregateBuffer->base() + bigSize, accessUnit->data(), smallSize);
+            bigSize += smallSize;
+            mAggregateBuffer->setRange(0, bigSize);
+
+            ALOGV("feedDecoderInputData() smallSize = %zu, bigSize = %zu, capacity = %zu",
+                    smallSize, bigSize, mAggregateBuffer->capacity());
+        }
+    } else {
+        // decided not to aggregate
+        aggregate = accessUnit;
+    }
+
+    return aggregate;
+}
+
+status_t NuPlayer::DecoderPassThrough::fetchInputData(sp<AMessage> &reply) {
+    sp<ABuffer> accessUnit;
+
+    do {
+        status_t err = dequeueAccessUnit(&accessUnit);
+
+        if (err == -EWOULDBLOCK) {
+            return err;
+        } else if (err != OK) {
+            if (err == INFO_DISCONTINUITY) {
+                int32_t type;
+                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
+
+                bool formatChange =
+                        (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
+
+                bool timeChange =
+                        (type & ATSParser::DISCONTINUITY_TIME) != 0;
+
+                ALOGI("audio discontinuity (formatChange=%d, time=%d)",
+                        formatChange, timeChange);
+
+                if (formatChange || timeChange) {
+                    sp<AMessage> msg = mNotify->dup();
+                    msg->setInt32("what", kWhatInputDiscontinuity);
+                    // will perform seamless format change,
+                    // only notify NuPlayer to scan sources
+                    msg->setInt32("formatChange", false);
+                    msg->post();
+                }
+
+                if (timeChange) {
+                    doFlush(false /* notifyComplete */);
+                    err = OK;
+                } else if (formatChange) {
+                    // do seamless format change
+                    err = OK;
+                } else {
+                    // This stream is unaffected by the discontinuity
+                    return -EWOULDBLOCK;
+                }
+            }
+
+            reply->setInt32("err", err);
+            return OK;
+        }
+
+        accessUnit = aggregateBuffer(accessUnit);
+    } while (accessUnit == NULL);
+
+#if 0
+    int64_t mediaTimeUs;
+    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
+    ALOGV("feeding audio input buffer at media time %.2f secs",
+         mediaTimeUs / 1E6);
+#endif
+
+    reply->setBuffer("buffer", accessUnit);
+
+    return OK;
+}
+
+void NuPlayer::DecoderPassThrough::onInputBufferFetched(
         const sp<AMessage> &msg) {
-    --mPendingBuffersToFill;
     if (mReachedEOS) {
         return;
     }
 
     sp<ABuffer> buffer;
-    msg->findBuffer("buffer", &buffer);
+    bool hasBuffer = msg->findBuffer("buffer", &buffer);
     if (buffer == NULL) {
-        mReachedEOS = true;
+        int32_t streamErr = ERROR_END_OF_STREAM;
+        CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
+        if (streamErr == OK) {
+            return;
+        }
 
-        sp<AMessage> notify = mNotify->dup();
-        notify->setInt32("what", kWhatEOS);
-        notify->setInt32("err", ERROR_END_OF_STREAM);
-        notify->post();
+        mReachedEOS = true;
+        if (mRenderer != NULL) {
+            mRenderer->queueEOS(true /* audio */, ERROR_END_OF_STREAM);
+        }
         return;
     }
 
-    mCachedBytes += buffer->size();
+    sp<AMessage> extra;
+    if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
+        int64_t resumeAtMediaTimeUs;
+        if (extra->findInt64(
+                    "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
+            ALOGI("[%s] suppressing rendering until %lld us",
+                    mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
+            mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
+        }
+    }
 
-    sp<AMessage> reply = new AMessage(kWhatBufferConsumed, id());
+    int32_t bufferSize = buffer->size();
+    mCachedBytes += bufferSize;
+
+    if (mSkipRenderingUntilMediaTimeUs >= 0) {
+        int64_t timeUs = 0;
+        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
+
+        if (timeUs < mSkipRenderingUntilMediaTimeUs) {
+            ALOGV("[%s] dropping buffer at time %lld as requested.",
+                     mComponentName.c_str(), (long long)timeUs);
+
+            onBufferConsumed(bufferSize);
+            return;
+        }
+
+        mSkipRenderingUntilMediaTimeUs = -1;
+    }
+
+    if (mRenderer == NULL) {
+        onBufferConsumed(bufferSize);
+        return;
+    }
+
+    sp<AMessage> reply = new AMessage(kWhatBufferConsumed, this);
     reply->setInt32("generation", mBufferGeneration);
-    reply->setInt32("size", buffer->size());
+    reply->setInt32("size", bufferSize);
 
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatDrainThisBuffer);
-    notify->setBuffer("buffer", buffer);
-    notify->setMessage("reply", reply);
-    notify->post();
+    mRenderer->queueBuffer(true /* audio */, buffer, reply);
+
     ++mPendingBuffersToDrain;
-    ALOGV("onInputBufferFilled: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu",
-            mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes);
+    ALOGV("onInputBufferFilled: #ToDrain = %zu, cachedBytes = %zu",
+            mPendingBuffersToDrain, mCachedBytes);
 }
 
 void NuPlayer::DecoderPassThrough::onBufferConsumed(int32_t size) {
     --mPendingBuffersToDrain;
     mCachedBytes -= size;
-    ALOGV("onBufferConsumed: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu",
-           mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes);
-    requestABuffer();
+    ALOGV("onBufferConsumed: #ToDrain = %zu, cachedBytes = %zu",
+            mPendingBuffersToDrain, mCachedBytes);
+    onRequestInputBuffers();
 }
 
-void NuPlayer::DecoderPassThrough::onFlush() {
-    ++mBufferGeneration;
+void NuPlayer::DecoderPassThrough::onResume(bool notifyComplete) {
+    mPaused = false;
 
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatFlushCompleted);
-    notify->post();
-    mPendingBuffersToFill = 0;
+    onRequestInputBuffers();
+
+    if (notifyComplete) {
+        sp<AMessage> notify = mNotify->dup();
+        notify->setInt32("what", kWhatResumeCompleted);
+        notify->post();
+    }
+}
+
+void NuPlayer::DecoderPassThrough::doFlush(bool notifyComplete) {
+    ++mBufferGeneration;
+    mSkipRenderingUntilMediaTimeUs = -1;
+    mPendingAudioAccessUnit.clear();
+    mPendingAudioErr = OK;
+    mAggregateBuffer.clear();
+
+    if (mRenderer != NULL) {
+        mRenderer->flush(true /* audio */, notifyComplete);
+        mRenderer->signalTimeDiscontinuity();
+    }
+
     mPendingBuffersToDrain = 0;
     mCachedBytes = 0;
     mReachedEOS = false;
 }
 
-void NuPlayer::DecoderPassThrough::requestMaxBuffers() {
-    for (size_t i = 0; i < kMaxPendingBuffers; i++) {
-        if (!requestABuffer()) {
-            break;
-        }
-    }
+void NuPlayer::DecoderPassThrough::onFlush() {
+    doFlush(true /* notifyComplete */);
+
+    mPaused = true;
+    sp<AMessage> notify = mNotify->dup();
+    notify->setInt32("what", kWhatFlushCompleted);
+    notify->post();
+
 }
 
-void NuPlayer::DecoderPassThrough::onShutdown() {
+void NuPlayer::DecoderPassThrough::onShutdown(bool notifyComplete) {
     ++mBufferGeneration;
+    mSkipRenderingUntilMediaTimeUs = -1;
 
-    sp<AMessage> notify = mNotify->dup();
-    notify->setInt32("what", kWhatShutdownCompleted);
-    notify->post();
+    if (notifyComplete) {
+        sp<AMessage> notify = mNotify->dup();
+        notify->setInt32("what", kWhatShutdownCompleted);
+        notify->post();
+    }
+
     mReachedEOS = true;
 }
 
@@ -204,31 +409,6 @@
             msg->debugString().c_str());
 
     switch (msg->what()) {
-        case kWhatConfigure:
-        {
-            sp<AMessage> format;
-            CHECK(msg->findMessage("format", &format));
-            onConfigure(format);
-            break;
-        }
-
-        case kWhatRequestABuffer:
-        {
-            if (!isStaleReply(msg)) {
-                requestABuffer();
-            }
-
-            break;
-        }
-
-        case kWhatInputBufferFilled:
-        {
-            if (!isStaleReply(msg)) {
-                onInputBufferFilled(msg);
-            }
-            break;
-        }
-
         case kWhatBufferConsumed:
         {
             if (!isStaleReply(msg)) {
@@ -239,26 +419,8 @@
             break;
         }
 
-        case kWhatFlush:
-        {
-            onFlush();
-            break;
-        }
-
-        case kWhatResume:
-        {
-            requestMaxBuffers();
-            break;
-        }
-
-        case kWhatShutdown:
-        {
-            onShutdown();
-            break;
-        }
-
         default:
-            TRESPASS();
+            DecoderBase::onMessageReceived(msg);
             break;
     }
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
index fb20257..173cfbd 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
@@ -20,21 +20,18 @@
 
 #include "NuPlayer.h"
 
-#include "NuPlayerDecoder.h"
+#include "NuPlayerDecoderBase.h"
 
 namespace android {
 
-struct NuPlayer::DecoderPassThrough : public Decoder {
-    DecoderPassThrough(const sp<AMessage> &notify);
+struct NuPlayer::DecoderPassThrough : public DecoderBase {
+    DecoderPassThrough(const sp<AMessage> &notify,
+                       const sp<Source> &source,
+                       const sp<Renderer> &renderer);
 
-    virtual void configure(const sp<AMessage> &format);
-    virtual void init();
-
-    virtual void signalFlush();
-    virtual void signalResume();
-    virtual void initiateShutdown();
-
-    bool supportsSeamlessFormatChange(const sp<AMessage> &to) const;
+    virtual void getStats(
+            int64_t *mNumFramesTotal,
+            int64_t *mNumFramesDropped) const;
 
 protected:
 
@@ -42,41 +39,49 @@
 
     virtual void onMessageReceived(const sp<AMessage> &msg);
 
+    virtual void onConfigure(const sp<AMessage> &format);
+    virtual void onSetRenderer(const sp<Renderer> &renderer);
+    virtual void onGetInputBuffers(Vector<sp<ABuffer> > *dstBuffers);
+    virtual void onResume(bool notifyComplete);
+    virtual void onFlush();
+    virtual void onShutdown(bool notifyComplete);
+    virtual void doRequestBuffers();
+
 private:
     enum {
-        kWhatRequestABuffer     = 'reqB',
-        kWhatConfigure          = 'conf',
-        kWhatInputBufferFilled  = 'inpF',
         kWhatBufferConsumed     = 'bufC',
-        kWhatFlush              = 'flus',
-        kWhatShutdown           = 'shuD',
     };
 
-    sp<AMessage> mNotify;
-    sp<ALooper> mDecoderLooper;
+    sp<Source> mSource;
+    sp<Renderer> mRenderer;
+    int64_t mSkipRenderingUntilMediaTimeUs;
+    bool mPaused;
 
-    /** Returns true if a buffer was requested.
-     * Returns false if at EOS or cache already full.
-     */
-    bool requestABuffer();
-    bool isStaleReply(const sp<AMessage> &msg);
-
-    void onConfigure(const sp<AMessage> &format);
-    void onFlush();
-    void onInputBufferFilled(const sp<AMessage> &msg);
-    void onBufferConsumed(int32_t size);
-    void requestMaxBuffers();
-    void onShutdown();
-
-    int32_t mBufferGeneration;
     bool    mReachedEOS;
-    // TODO mPendingBuffersToFill and mPendingBuffersToDrain are only for
-    // debugging. They can be removed when the power investigation is done.
-    size_t  mPendingBuffersToFill;
+
+    // Used by feedDecoderInputData to aggregate small buffers into
+    // one large buffer.
+    sp<ABuffer> mPendingAudioAccessUnit;
+    status_t    mPendingAudioErr;
+    sp<ABuffer> mAggregateBuffer;
+
+    // mPendingBuffersToDrain are only for debugging. It can be removed
+    // when the power investigation is done.
     size_t  mPendingBuffersToDrain;
     size_t  mCachedBytes;
     AString mComponentName;
 
+    bool isStaleReply(const sp<AMessage> &msg);
+    bool isDoneFetching() const;
+
+    status_t dequeueAccessUnit(sp<ABuffer> *accessUnit);
+    sp<ABuffer> aggregateBuffer(const sp<ABuffer> &accessUnit);
+    status_t fetchInputData(sp<AMessage> &reply);
+    void doFlush(bool notifyComplete);
+
+    void onInputBufferFetched(const sp<AMessage> &msg);
+    void onBufferConsumed(int32_t size);
+
     DISALLOW_EVIL_CONSTRUCTORS(DecoderPassThrough);
 };
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 2b1c559..5887e50 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -310,6 +310,13 @@
 }
 
 status_t NuPlayerDriver::pause() {
+    // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
+    // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
+    // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
+    // getCurrentPosition here.
+    int msec;
+    getCurrentPosition(&msec);
+
     Mutex::Autolock autoLock(mLock);
 
     switch (mState) {
@@ -334,6 +341,11 @@
     return mState == STATE_RUNNING && !mAtEOS;
 }
 
+status_t NuPlayerDriver::setPlaybackRate(float rate) {
+    mPlayer->setPlaybackRate(rate);
+    return OK;
+}
+
 status_t NuPlayerDriver::seekTo(int msec) {
     ALOGD("seekTo(%p) %d ms", this, msec);
     Mutex::Autolock autoLock(mLock);
@@ -381,13 +393,22 @@
 
 status_t NuPlayerDriver::getCurrentPosition(int *msec) {
     int64_t tempUs = 0;
+    {
+        Mutex::Autolock autoLock(mLock);
+        if (mSeekInProgress || mState == STATE_PAUSED) {
+            tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
+            *msec = (int)divRound(tempUs, (int64_t)(1000));
+            return OK;
+        }
+    }
+
     status_t ret = mPlayer->getCurrentPosition(&tempUs);
 
     Mutex::Autolock autoLock(mLock);
     // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
     // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
     // position value that's different the seek to position.
-    if (ret != OK || mSeekInProgress) {
+    if (ret != OK) {
         tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
     } else {
         mPositionUs = tempUs;
@@ -488,13 +509,16 @@
         case INVOKE_ID_SELECT_TRACK:
         {
             int trackIndex = request.readInt32();
-            return mPlayer->selectTrack(trackIndex, true /* select */);
+            int msec = 0;
+            // getCurrentPosition should always return OK
+            getCurrentPosition(&msec);
+            return mPlayer->selectTrack(trackIndex, true /* select */, msec * 1000ll);
         }
 
         case INVOKE_ID_UNSELECT_TRACK:
         {
             int trackIndex = request.readInt32();
-            return mPlayer->selectTrack(trackIndex, false /* select */);
+            return mPlayer->selectTrack(trackIndex, false /* select */, 0xdeadbeef /* not used */);
         }
 
         case INVOKE_ID_GET_SELECTED_TRACK:
@@ -633,9 +657,23 @@
         case MEDIA_PLAYBACK_COMPLETE:
         {
             if (mState != STATE_RESET_IN_PROGRESS) {
-                if (mLooping || (mAutoLoop
-                        && (mAudioSink == NULL || mAudioSink->realtime()))) {
+                if (mAutoLoop) {
+                    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");
+                        mAutoLoop = false;
+                    }
+                }
+                if (mLooping || mAutoLoop) {
                     mPlayer->seekToAsync(0);
+                    if (mAudioSink != NULL) {
+                        // The renderer has stopped the sink at the end in order to play out
+                        // the last little bit of audio. If we're looping, we need to restart it.
+                        mAudioSink->start();
+                    }
                     break;
                 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 5cba7d9..e53abcd 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -47,6 +47,7 @@
     virtual status_t stop();
     virtual status_t pause();
     virtual bool isPlaying();
+    virtual status_t setPlaybackRate(float rate);
     virtual status_t seekTo(int msec);
     virtual status_t getCurrentPosition(int *msec);
     virtual status_t getDuration(int *msec);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 5d9001c..a2ec51c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -20,12 +20,12 @@
 
 #include "NuPlayerRenderer.h"
 
-#include <cutils/properties.h>
-
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/foundation/AWakeLock.h>
+#include <media/stagefright/MediaClock.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/Utils.h>
@@ -41,18 +41,17 @@
 static const int64_t kOffloadPauseMaxUs = 10000000ll;
 
 // static
+const NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {
+        AUDIO_CHANNEL_NONE,
+        AUDIO_OUTPUT_FLAG_NONE,
+        AUDIO_FORMAT_INVALID,
+        0, // mNumChannels
+        0 // mSampleRate
+};
+
+// static
 const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
 
-static bool sFrameAccurateAVsync = false;
-
-static void readProperties() {
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("persist.sys.media.avsync", value, NULL)) {
-        sFrameAccurateAVsync =
-            !strcmp("1", value) || !strcasecmp("true", value);
-    }
-}
-
 NuPlayer::Renderer::Renderer(
         const sp<MediaPlayerBase::AudioSink> &sink,
         const sp<AMessage> &notify,
@@ -65,17 +64,17 @@
       mDrainVideoQueuePending(false),
       mAudioQueueGeneration(0),
       mVideoQueueGeneration(0),
+      mAudioDrainGeneration(0),
+      mVideoDrainGeneration(0),
+      mPlaybackRate(1.0),
       mAudioFirstAnchorTimeMediaUs(-1),
       mAnchorTimeMediaUs(-1),
-      mAnchorTimeRealUs(-1),
       mAnchorNumFramesWritten(-1),
-      mAnchorMaxMediaUs(-1),
       mVideoLateByUs(0ll),
       mHasAudio(false),
       mHasVideo(false),
-      mPauseStartedTimeRealUs(-1),
-      mFlushingAudio(false),
-      mFlushingVideo(false),
+      mNotifyCompleteAudio(false),
+      mNotifyCompleteVideo(false),
       mSyncQueues(false),
       mPaused(false),
       mVideoSampleReceived(false),
@@ -85,9 +84,11 @@
       mAudioOffloadPauseTimeoutGeneration(0),
       mAudioOffloadTornDown(false),
       mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
+      mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
       mTotalBuffersQueued(0),
-      mLastAudioBufferDrained(0) {
-    readProperties();
+      mLastAudioBufferDrained(0),
+      mWakeLock(new AWakeLock()) {
+    mMediaClock = new MediaClock;
 }
 
 NuPlayer::Renderer::~Renderer() {
@@ -102,7 +103,8 @@
         bool audio,
         const sp<ABuffer> &buffer,
         const sp<AMessage> &notifyConsumed) {
-    sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
+    sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
+    msg->setInt32("queueGeneration", getQueueGeneration(audio));
     msg->setInt32("audio", static_cast<int32_t>(audio));
     msg->setBuffer("buffer", buffer);
     msg->setMessage("notifyConsumed", notifyConsumed);
@@ -112,155 +114,108 @@
 void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
     CHECK_NE(finalResult, (status_t)OK);
 
-    sp<AMessage> msg = new AMessage(kWhatQueueEOS, id());
+    sp<AMessage> msg = new AMessage(kWhatQueueEOS, this);
+    msg->setInt32("queueGeneration", getQueueGeneration(audio));
     msg->setInt32("audio", static_cast<int32_t>(audio));
     msg->setInt32("finalResult", finalResult);
     msg->post();
 }
 
-void NuPlayer::Renderer::flush(bool audio) {
+void NuPlayer::Renderer::setPlaybackRate(float rate) {
+    sp<AMessage> msg = new AMessage(kWhatSetRate, this);
+    msg->setFloat("rate", rate);
+    msg->post();
+}
+
+void NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
     {
-        Mutex::Autolock autoLock(mFlushLock);
+        Mutex::Autolock autoLock(mLock);
         if (audio) {
-            if (mFlushingAudio) {
-                return;
-            }
-            mFlushingAudio = true;
+            mNotifyCompleteAudio |= notifyComplete;
+            ++mAudioQueueGeneration;
+            ++mAudioDrainGeneration;
         } else {
-            if (mFlushingVideo) {
-                return;
-            }
-            mFlushingVideo = true;
+            mNotifyCompleteVideo |= notifyComplete;
+            ++mVideoQueueGeneration;
+            ++mVideoDrainGeneration;
         }
+
+        clearAnchorTime_l();
+        clearAudioFirstAnchorTime_l();
+        mVideoLateByUs = 0;
+        mSyncQueues = false;
     }
 
-    sp<AMessage> msg = new AMessage(kWhatFlush, id());
+    sp<AMessage> msg = new AMessage(kWhatFlush, this);
     msg->setInt32("audio", static_cast<int32_t>(audio));
     msg->post();
 }
 
 void NuPlayer::Renderer::signalTimeDiscontinuity() {
-    Mutex::Autolock autoLock(mLock);
-    // CHECK(mAudioQueue.empty());
-    // CHECK(mVideoQueue.empty());
-    setAudioFirstAnchorTime(-1);
-    setAnchorTime(-1, -1);
-    setVideoLateByUs(0);
-    mSyncQueues = false;
-}
-
-void NuPlayer::Renderer::signalAudioSinkChanged() {
-    (new AMessage(kWhatAudioSinkChanged, id()))->post();
 }
 
 void NuPlayer::Renderer::signalDisableOffloadAudio() {
-    (new AMessage(kWhatDisableOffloadAudio, id()))->post();
+    (new AMessage(kWhatDisableOffloadAudio, this))->post();
+}
+
+void NuPlayer::Renderer::signalEnableOffloadAudio() {
+    (new AMessage(kWhatEnableOffloadAudio, this))->post();
 }
 
 void NuPlayer::Renderer::pause() {
-    (new AMessage(kWhatPause, id()))->post();
+    (new AMessage(kWhatPause, this))->post();
 }
 
 void NuPlayer::Renderer::resume() {
-    (new AMessage(kWhatResume, id()))->post();
+    (new AMessage(kWhatResume, this))->post();
 }
 
 void NuPlayer::Renderer::setVideoFrameRate(float fps) {
-    sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, id());
+    sp<AMessage> msg = new AMessage(kWhatSetVideoFrameRate, this);
     msg->setFloat("frame-rate", fps);
     msg->post();
 }
 
+// Called on any threads.
 status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
-    return getCurrentPosition(mediaUs, ALooper::GetNowUs());
+    return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
 }
 
-status_t NuPlayer::Renderer::getCurrentPosition(
-        int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) {
-    Mutex::Autolock autoLock(mTimeLock);
-    if (!mHasAudio && !mHasVideo) {
-        return NO_INIT;
-    }
-
-    if (mAnchorTimeMediaUs < 0) {
-        return NO_INIT;
-    }
-
-    int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
-
-    if (mPauseStartedTimeRealUs != -1) {
-        positionUs -= (nowUs - mPauseStartedTimeRealUs);
-    }
-
-    // limit position to the last queued media time (for video only stream
-    // position will be discrete as we don't know how long each frame lasts)
-    if (mAnchorMaxMediaUs >= 0 && !allowPastQueuedVideo) {
-        if (positionUs > mAnchorMaxMediaUs) {
-            positionUs = mAnchorMaxMediaUs;
-        }
-    }
-
-    if (positionUs < mAudioFirstAnchorTimeMediaUs) {
-        positionUs = mAudioFirstAnchorTimeMediaUs;
-    }
-
-    *mediaUs = (positionUs <= 0) ? 0 : positionUs;
-    return OK;
+void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
+    mAudioFirstAnchorTimeMediaUs = -1;
+    mMediaClock->setStartingTimeMedia(-1);
 }
 
-void NuPlayer::Renderer::setHasMedia(bool audio) {
-    Mutex::Autolock autoLock(mTimeLock);
-    if (audio) {
-        mHasAudio = true;
-    } else {
-        mHasVideo = true;
-    }
-}
-
-void NuPlayer::Renderer::setAudioFirstAnchorTime(int64_t mediaUs) {
-    Mutex::Autolock autoLock(mTimeLock);
-    mAudioFirstAnchorTimeMediaUs = mediaUs;
-}
-
-void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs) {
-    Mutex::Autolock autoLock(mTimeLock);
+void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
     if (mAudioFirstAnchorTimeMediaUs == -1) {
         mAudioFirstAnchorTimeMediaUs = mediaUs;
+        mMediaClock->setStartingTimeMedia(mediaUs);
     }
 }
 
-void NuPlayer::Renderer::setAnchorTime(
-        int64_t mediaUs, int64_t realUs, int64_t numFramesWritten, bool resume) {
-    Mutex::Autolock autoLock(mTimeLock);
-    mAnchorTimeMediaUs = mediaUs;
-    mAnchorTimeRealUs = realUs;
-    mAnchorNumFramesWritten = numFramesWritten;
-    if (resume) {
-        mPauseStartedTimeRealUs = -1;
-    }
+void NuPlayer::Renderer::clearAnchorTime_l() {
+    mMediaClock->clearAnchor();
+    mAnchorTimeMediaUs = -1;
+    mAnchorNumFramesWritten = -1;
 }
 
 void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
-    Mutex::Autolock autoLock(mTimeLock);
+    Mutex::Autolock autoLock(mLock);
     mVideoLateByUs = lateUs;
 }
 
 int64_t NuPlayer::Renderer::getVideoLateByUs() {
-    Mutex::Autolock autoLock(mTimeLock);
+    Mutex::Autolock autoLock(mLock);
     return mVideoLateByUs;
 }
 
-void NuPlayer::Renderer::setPauseStartedTimeRealUs(int64_t realUs) {
-    Mutex::Autolock autoLock(mTimeLock);
-    mPauseStartedTimeRealUs = realUs;
-}
-
-bool NuPlayer::Renderer::openAudioSink(
+status_t NuPlayer::Renderer::openAudioSink(
         const sp<AMessage> &format,
         bool offloadOnly,
         bool hasVideo,
-        uint32_t flags) {
-    sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, id());
+        uint32_t flags,
+        bool *isOffloaded) {
+    sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
     msg->setMessage("format", format);
     msg->setInt32("offload-only", offloadOnly);
     msg->setInt32("has-video", hasVideo);
@@ -269,13 +224,19 @@
     sp<AMessage> response;
     msg->postAndAwaitResponse(&response);
 
-    int32_t offload;
-    CHECK(response->findInt32("offload", &offload));
-    return (offload != 0);
+    int32_t err;
+    if (!response->findInt32("err", &err)) {
+        err = INVALID_OPERATION;
+    } else if (err == OK && isOffloaded != NULL) {
+        int32_t offload;
+        CHECK(response->findInt32("offload", &offload));
+        *isOffloaded = (offload != 0);
+    }
+    return err;
 }
 
 void NuPlayer::Renderer::closeAudioSink() {
-    sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, id());
+    sp<AMessage> msg = new AMessage(kWhatCloseAudioSink, this);
 
     sp<AMessage> response;
     msg->postAndAwaitResponse(&response);
@@ -297,12 +258,13 @@
             uint32_t flags;
             CHECK(msg->findInt32("flags", (int32_t *)&flags));
 
-            bool offload = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
+            status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
 
             sp<AMessage> response = new AMessage;
-            response->setInt32("offload", offload);
+            response->setInt32("err", err);
+            response->setInt32("offload", offloadingAudio());
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
             response->postReply(replyID);
 
@@ -311,7 +273,7 @@
 
         case kWhatCloseAudioSink:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             onCloseAudioSink();
@@ -330,8 +292,8 @@
         case kWhatDrainAudioQueue:
         {
             int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-            if (generation != mAudioQueueGeneration) {
+            CHECK(msg->findInt32("drainGeneration", &generation));
+            if (generation != getDrainGeneration(true /* audio */)) {
                 break;
             }
 
@@ -353,9 +315,7 @@
 
                 // Let's give it more data after about half that time
                 // has elapsed.
-                // kWhatDrainAudioQueue is used for non-offloading mode,
-                // and mLock is used only for offloading mode. Therefore,
-                // no need to acquire mLock here.
+                Mutex::Autolock autoLock(mLock);
                 postDrainAudioQueue_l(delayUs / 2);
             }
             break;
@@ -364,8 +324,8 @@
         case kWhatDrainVideoQueue:
         {
             int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-            if (generation != mVideoQueueGeneration) {
+            CHECK(msg->findInt32("drainGeneration", &generation));
+            if (generation != getDrainGeneration(false /* audio */)) {
                 break;
             }
 
@@ -380,8 +340,8 @@
         case kWhatPostDrainVideoQueue:
         {
             int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-            if (generation != mVideoQueueGeneration) {
+            CHECK(msg->findInt32("drainGeneration", &generation));
+            if (generation != getDrainGeneration(false /* audio */)) {
                 break;
             }
 
@@ -402,24 +362,34 @@
             break;
         }
 
+        case kWhatSetRate:
+        {
+            CHECK(msg->findFloat("rate", &mPlaybackRate));
+            int32_t ratePermille = (int32_t)(0.5f + 1000 * mPlaybackRate);
+            mPlaybackRate = ratePermille / 1000.0f;
+            mMediaClock->setPlaybackRate(mPlaybackRate);
+            mAudioSink->setPlaybackRatePermille(ratePermille);
+            break;
+        }
+
         case kWhatFlush:
         {
             onFlush(msg);
             break;
         }
 
-        case kWhatAudioSinkChanged:
-        {
-            onAudioSinkChanged();
-            break;
-        }
-
         case kWhatDisableOffloadAudio:
         {
             onDisableOffloadAudio();
             break;
         }
 
+        case kWhatEnableOffloadAudio:
+        {
+            onEnableOffloadAudio();
+            break;
+        }
+
         case kWhatPause:
         {
             onPause();
@@ -449,12 +419,13 @@
         case kWhatAudioOffloadPauseTimeout:
         {
             int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
+            CHECK(msg->findInt32("drainGeneration", &generation));
             if (generation != mAudioOffloadPauseTimeoutGeneration) {
                 break;
             }
             ALOGV("Audio Offload tear down due to pause timeout.");
             onAudioOffloadTearDown(kDueToTimeout);
+            mWakeLock->release();
             break;
         }
 
@@ -475,19 +446,19 @@
     }
 
     mDrainAudioQueuePending = true;
-    sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
-    msg->setInt32("generation", mAudioQueueGeneration);
+    sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
+    msg->setInt32("drainGeneration", mAudioDrainGeneration);
     msg->post(delayUs);
 }
 
-void NuPlayer::Renderer::prepareForMediaRenderingStart() {
-    mAudioRenderingStartGeneration = mAudioQueueGeneration;
-    mVideoRenderingStartGeneration = mVideoQueueGeneration;
+void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
+    mAudioRenderingStartGeneration = mAudioDrainGeneration;
+    mVideoRenderingStartGeneration = mVideoDrainGeneration;
 }
 
-void NuPlayer::Renderer::notifyIfMediaRenderingStarted() {
-    if (mVideoRenderingStartGeneration == mVideoQueueGeneration &&
-        mAudioRenderingStartGeneration == mAudioQueueGeneration) {
+void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
+    if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
+        mAudioRenderingStartGeneration == mAudioDrainGeneration) {
         mVideoRenderingStartGeneration = -1;
         mAudioRenderingStartGeneration = -1;
 
@@ -555,7 +526,7 @@
             int64_t mediaTimeUs;
             CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
             ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
-            setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
+            setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
         }
 
         size_t copy = entry->mBuffer->size() - entry->mOffset;
@@ -575,34 +546,45 @@
             entry = NULL;
         }
         sizeCopied += copy;
-        notifyIfMediaRenderingStarted();
+
+        notifyIfMediaRenderingStarted_l();
     }
 
     if (mAudioFirstAnchorTimeMediaUs >= 0) {
         int64_t nowUs = ALooper::GetNowUs();
-        setAnchorTime(mAudioFirstAnchorTimeMediaUs, nowUs - getPlayedOutAudioDurationUs(nowUs));
+        int64_t nowMediaUs =
+            mAudioFirstAnchorTimeMediaUs + getPlayedOutAudioDurationUs(nowUs);
+        // we don't know how much data we are queueing for offloaded tracks.
+        mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
     }
 
-    // we don't know how much data we are queueing for offloaded tracks
-    mAnchorMaxMediaUs = -1;
-
     if (hasEOS) {
-        (new AMessage(kWhatStopAudioSink, id()))->post();
+        (new AMessage(kWhatStopAudioSink, this))->post();
     }
 
     return sizeCopied;
 }
 
 bool NuPlayer::Renderer::onDrainAudioQueue() {
+    // TODO: This call to getPosition checks if AudioTrack has been created
+    // in AudioSink before draining audio. If AudioTrack doesn't exist, then
+    // CHECKs on getPosition will fail.
+    // We still need to figure out why AudioTrack is not created when
+    // this function is called. One possible reason could be leftover
+    // audio. Another possible place is to check whether decoder
+    // has received INFO_FORMAT_CHANGED as the first buffer since
+    // AudioSink is opened there, and possible interactions with flush
+    // immediately after start. Investigate error message
+    // "vorbis_dsp_synthesis returned -135", along with RTSP.
     uint32_t numFramesPlayed;
     if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
         return false;
     }
 
+#if 0
     ssize_t numFramesAvailableToWrite =
         mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
 
-#if 0
     if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
         ALOGI("audio sink underrun");
     } else {
@@ -611,10 +593,7 @@
     }
 #endif
 
-    size_t numBytesAvailableToWrite =
-        numFramesAvailableToWrite * mAudioSink->frameSize();
-
-    while (numBytesAvailableToWrite > 0 && !mAudioQueue.empty()) {
+    while (!mAudioQueue.empty()) {
         QueueEntry *entry = &*mAudioQueue.begin();
 
         mLastAudioBufferDrained = entry->mBufferOrdinal;
@@ -629,6 +608,13 @@
 
             mAudioQueue.erase(mAudioQueue.begin());
             entry = NULL;
+            if (mAudioSink->needsTrailingPadding()) {
+                // If we're not in gapless playback (i.e. through setNextPlayer), we
+                // need to stop the track here, because that will play out the last
+                // little bit at the end of the file. Otherwise short files won't play.
+                mAudioSink->stop();
+                mNumFramesWritten = 0;
+            }
             return false;
         }
 
@@ -640,14 +626,17 @@
         }
 
         size_t copy = entry->mBuffer->size() - entry->mOffset;
-        if (copy > numBytesAvailableToWrite) {
-            copy = numBytesAvailableToWrite;
-        }
 
-        ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset, copy);
+        ssize_t written = mAudioSink->write(entry->mBuffer->data() + entry->mOffset,
+                                            copy, false /* blocking */);
         if (written < 0) {
-            // An error in AudioSink write is fatal here.
-            LOG_ALWAYS_FATAL("AudioSink write error(%zd) when writing %zu bytes", written, copy);
+            // An error in AudioSink write. Perhaps the AudioSink was not properly opened.
+            if (written == WOULD_BLOCK) {
+                ALOGW("AudioSink write would block when writing %zu bytes", copy);
+            } else {
+                ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
+            }
+            break;
         }
 
         entry->mOffset += written;
@@ -658,72 +647,92 @@
             entry = NULL;
         }
 
-        numBytesAvailableToWrite -= written;
         size_t copiedFrames = written / mAudioSink->frameSize();
         mNumFramesWritten += copiedFrames;
 
-        notifyIfMediaRenderingStarted();
+        {
+            Mutex::Autolock autoLock(mLock);
+            notifyIfMediaRenderingStarted_l();
+        }
 
         if (written != (ssize_t)copy) {
             // A short count was received from AudioSink::write()
             //
-            // AudioSink write should block until exactly the number of bytes are delivered.
-            // But it may return with a short count (without an error) when:
+            // AudioSink write is called in non-blocking mode.
+            // It may return with a short count when:
             //
             // 1) Size to be copied is not a multiple of the frame size. We consider this fatal.
-            // 2) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
+            // 2) The data to be copied exceeds the available buffer in AudioSink.
+            // 3) An error occurs and data has been partially copied to the buffer in AudioSink.
+            // 4) AudioSink is an AudioCache for data retrieval, and the AudioCache is exceeded.
 
             // (Case 1)
             // Must be a multiple of the frame size.  If it is not a multiple of a frame size, it
             // needs to fail, as we should not carry over fractional frames between calls.
             CHECK_EQ(copy % mAudioSink->frameSize(), 0);
 
-            // (Case 2)
+            // (Case 2, 3, 4)
             // Return early to the caller.
             // Beware of calling immediately again as this may busy-loop if you are not careful.
-            ALOGW("AudioSink write short frame count %zd < %zu", written, copy);
+            ALOGV("AudioSink write short frame count %zd < %zu", written, copy);
             break;
         }
     }
-    mAnchorMaxMediaUs =
-        mAnchorTimeMediaUs +
-                (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
-                        * 1000LL * mAudioSink->msecsPerFrame());
+    int64_t maxTimeMedia;
+    {
+        Mutex::Autolock autoLock(mLock);
+        maxTimeMedia =
+            mAnchorTimeMediaUs +
+                    (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
+                            * 1000LL * mAudioSink->msecsPerFrame());
+    }
+    mMediaClock->updateMaxTimeMedia(maxTimeMedia);
 
     return !mAudioQueue.empty();
 }
 
+int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
+    int32_t sampleRate = offloadingAudio() ?
+            mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
+    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
+    return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
+}
+
+// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
 int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
-    int64_t writtenAudioDurationUs =
-        mNumFramesWritten * 1000LL * mAudioSink->msecsPerFrame();
+    int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
     return writtenAudioDurationUs - getPlayedOutAudioDurationUs(nowUs);
 }
 
 int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
-    int64_t currentPositionUs;
-    if (getCurrentPosition(&currentPositionUs, nowUs, true /* allowPastQueuedVideo */) != OK) {
-        // If failed to get current position, e.g. due to audio clock is not ready, then just
-        // play out video immediately without delay.
+    int64_t realUs;
+    if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
+        // If failed to get current position, e.g. due to audio clock is
+        // not ready, then just play out video immediately without delay.
         return nowUs;
     }
-    return (mediaTimeUs - currentPositionUs) + nowUs;
+    return realUs;
 }
 
 void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
+    Mutex::Autolock autoLock(mLock);
     // TRICKY: vorbis decoder generates multiple frames with the same
     // timestamp, so only update on the first frame with a given timestamp
     if (mediaTimeUs == mAnchorTimeMediaUs) {
         return;
     }
-    setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
+    setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
     int64_t nowUs = ALooper::GetNowUs();
-    setAnchorTime(
-            mediaTimeUs, nowUs + getPendingAudioPlayoutDurationUs(nowUs), mNumFramesWritten);
+    int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
+    mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
+    mAnchorNumFramesWritten = mNumFramesWritten;
+    mAnchorTimeMediaUs = mediaTimeUs;
 }
 
+// Called without mLock acquired.
 void NuPlayer::Renderer::postDrainVideoQueue() {
     if (mDrainVideoQueuePending
-            || mSyncQueues
+            || getSyncQueues()
             || (mPaused && mVideoSampleReceived)) {
         return;
     }
@@ -734,8 +743,8 @@
 
     QueueEntry &entry = *mVideoQueue.begin();
 
-    sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, id());
-    msg->setInt32("generation", mVideoQueueGeneration);
+    sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, this);
+    msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
 
     if (entry.mBuffer == NULL) {
         // EOS doesn't carry a timestamp.
@@ -755,14 +764,19 @@
         int64_t mediaTimeUs;
         CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
 
-        if (mAnchorTimeMediaUs < 0) {
-            setAnchorTime(mediaTimeUs, nowUs);
-            realTimeUs = nowUs;
-        } else {
-            realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
+        {
+            Mutex::Autolock autoLock(mLock);
+            if (mAnchorTimeMediaUs < 0) {
+                mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
+                mAnchorTimeMediaUs = mediaTimeUs;
+                realTimeUs = nowUs;
+            } else {
+                realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
+            }
         }
         if (!mHasAudio) {
-            mAnchorMaxMediaUs = mediaTimeUs + 100000; // smooth out videos >= 10fps
+            // smooth out videos >= 10fps
+            mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
         }
 
         // Heuristics to handle situation when media time changed without a
@@ -792,11 +806,6 @@
 
     ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
     // post 2 display refreshes before rendering is due
-    // FIXME currently this increases power consumption, so unless frame-accurate
-    // AV sync is requested, post closer to required render time (at 0.63 vsyncs)
-    if (!sFrameAccurateAVsync) {
-        twoVsyncsUs >>= 4;
-    }
     msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
 
     mDrainVideoQueuePending = true;
@@ -846,16 +855,19 @@
             ALOGV("video late by %lld us (%.2f secs)",
                  mVideoLateByUs, mVideoLateByUs / 1E6);
         } else {
+            int64_t mediaUs = 0;
+            mMediaClock->getMediaTime(realTimeUs, &mediaUs);
             ALOGV("rendering video at media time %.2f secs",
                     (mFlags & FLAG_REAL_TIME ? realTimeUs :
-                    (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6);
+                    mediaUs) / 1E6);
         }
     } else {
         setVideoLateByUs(0);
         if (!mVideoSampleReceived && !mHasAudio) {
             // This will ensure that the first frame after a flush won't be used as anchor
             // when renderer is in paused state, because resume can happen any time after seek.
-            setAnchorTime(-1, -1);
+            Mutex::Autolock autoLock(mLock);
+            clearAnchorTime_l();
         }
     }
 
@@ -872,7 +884,8 @@
             mVideoRenderingStarted = true;
             notifyVideoRenderingStart();
         }
-        notifyIfMediaRenderingStarted();
+        Mutex::Autolock autoLock(mLock);
+        notifyIfMediaRenderingStarted_l();
     }
 }
 
@@ -891,14 +904,22 @@
 }
 
 void NuPlayer::Renderer::notifyAudioOffloadTearDown() {
-    (new AMessage(kWhatAudioOffloadTearDown, id()))->post();
+    (new AMessage(kWhatAudioOffloadTearDown, this))->post();
 }
 
 void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
     int32_t audio;
     CHECK(msg->findInt32("audio", &audio));
 
-    setHasMedia(audio);
+    if (dropBufferIfStale(audio, msg)) {
+        return;
+    }
+
+    if (audio) {
+        mHasAudio = true;
+    } else {
+        mHasVideo = true;
+    }
 
     if (mHasVideo) {
         if (mVideoScheduler == NULL) {
@@ -907,10 +928,6 @@
         }
     }
 
-    if (dropBufferWhileFlushing(audio, msg)) {
-        return;
-    }
-
     sp<ABuffer> buffer;
     CHECK(msg->findBuffer("buffer", &buffer));
 
@@ -982,7 +999,9 @@
     }
 
     if (!mVideoQueue.empty()) {
+        mLock.unlock();
         postDrainVideoQueue();
+        mLock.lock();
     }
 }
 
@@ -990,7 +1009,7 @@
     int32_t audio;
     CHECK(msg->findInt32("audio", &audio));
 
-    if (dropBufferWhileFlushing(audio, msg)) {
+    if (dropBufferIfStale(audio, msg)) {
         return;
     }
 
@@ -1009,7 +1028,7 @@
         mAudioQueue.push_back(entry);
         postDrainAudioQueue_l();
     } else {
-        if (mVideoQueue.empty() && mSyncQueues) {
+        if (mVideoQueue.empty() && getSyncQueues()) {
             Mutex::Autolock autoLock(mLock);
             syncQueuesDone_l();
         }
@@ -1019,30 +1038,29 @@
 }
 
 void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
-    int32_t audio;
+    int32_t audio, notifyComplete;
     CHECK(msg->findInt32("audio", &audio));
 
     {
-        Mutex::Autolock autoLock(mFlushLock);
+        Mutex::Autolock autoLock(mLock);
         if (audio) {
-            mFlushingAudio = false;
+            notifyComplete = mNotifyCompleteAudio;
+            mNotifyCompleteAudio = false;
         } else {
-            mFlushingVideo = false;
+            notifyComplete = mNotifyCompleteVideo;
+            mNotifyCompleteVideo = false;
         }
-    }
 
-    // If we're currently syncing the queues, i.e. dropping audio while
-    // aligning the first audio/video buffer times and only one of the
-    // two queues has data, we may starve that queue by not requesting
-    // more buffers from the decoder. If the other source then encounters
-    // a discontinuity that leads to flushing, we'll never find the
-    // corresponding discontinuity on the other queue.
-    // Therefore we'll stop syncing the queues if at least one of them
-    // is flushed.
-    {
-         Mutex::Autolock autoLock(mLock);
-         syncQueuesDone_l();
-         setPauseStartedTimeRealUs(-1);
+        // If we're currently syncing the queues, i.e. dropping audio while
+        // aligning the first audio/video buffer times and only one of the
+        // two queues has data, we may starve that queue by not requesting
+        // more buffers from the decoder. If the other source then encounters
+        // a discontinuity that leads to flushing, we'll never find the
+        // corresponding discontinuity on the other queue.
+        // Therefore we'll stop syncing the queues if at least one of them
+        // is flushed.
+        syncQueuesDone_l();
+        clearAnchorTime_l();
     }
 
     ALOGV("flushing %s", audio ? "audio" : "video");
@@ -1051,11 +1069,11 @@
             Mutex::Autolock autoLock(mLock);
             flushQueue(&mAudioQueue);
 
-            ++mAudioQueueGeneration;
-            prepareForMediaRenderingStart();
+            ++mAudioDrainGeneration;
+            prepareForMediaRenderingStart_l();
 
             if (offloadingAudio()) {
-                setAudioFirstAnchorTime(-1);
+                clearAudioFirstAnchorTime_l();
             }
         }
 
@@ -1070,17 +1088,21 @@
         flushQueue(&mVideoQueue);
 
         mDrainVideoQueuePending = false;
-        ++mVideoQueueGeneration;
 
         if (mVideoScheduler != NULL) {
             mVideoScheduler->restart();
         }
 
-        prepareForMediaRenderingStart();
+        Mutex::Autolock autoLock(mLock);
+        ++mVideoDrainGeneration;
+        prepareForMediaRenderingStart_l();
     }
 
     mVideoSampleReceived = false;
-    notifyFlushComplete(audio);
+
+    if (notifyComplete) {
+        notifyFlushComplete(audio);
+    }
 }
 
 void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
@@ -1103,20 +1125,12 @@
     notify->post();
 }
 
-bool NuPlayer::Renderer::dropBufferWhileFlushing(
+bool NuPlayer::Renderer::dropBufferIfStale(
         bool audio, const sp<AMessage> &msg) {
-    bool flushing = false;
+    int32_t queueGeneration;
+    CHECK(msg->findInt32("queueGeneration", &queueGeneration));
 
-    {
-        Mutex::Autolock autoLock(mFlushLock);
-        if (audio) {
-            flushing = mFlushingAudio;
-        } else {
-            flushing = mFlushingVideo;
-        }
-    }
-
-    if (!flushing) {
+    if (queueGeneration == getQueueGeneration(audio)) {
         return false;
     }
 
@@ -1134,7 +1148,10 @@
     }
     CHECK(!mDrainAudioQueuePending);
     mNumFramesWritten = 0;
-    mAnchorNumFramesWritten = -1;
+    {
+        Mutex::Autolock autoLock(mLock);
+        mAnchorNumFramesWritten = -1;
+    }
     uint32_t written;
     if (mAudioSink->getFramesWritten(&written) == OK) {
         mNumFramesWritten = written;
@@ -1144,7 +1161,13 @@
 void NuPlayer::Renderer::onDisableOffloadAudio() {
     Mutex::Autolock autoLock(mLock);
     mFlags &= ~FLAG_OFFLOAD_AUDIO;
-    ++mAudioQueueGeneration;
+    ++mAudioDrainGeneration;
+}
+
+void NuPlayer::Renderer::onEnableOffloadAudio() {
+    Mutex::Autolock autoLock(mLock);
+    mFlags |= FLAG_OFFLOAD_AUDIO;
+    ++mAudioDrainGeneration;
 }
 
 void NuPlayer::Renderer::onPause() {
@@ -1152,13 +1175,14 @@
         ALOGW("Renderer::onPause() called while already paused!");
         return;
     }
+    int64_t currentPositionUs;
     {
         Mutex::Autolock autoLock(mLock);
-        ++mAudioQueueGeneration;
-        ++mVideoQueueGeneration;
-        prepareForMediaRenderingStart();
+        ++mAudioDrainGeneration;
+        ++mVideoDrainGeneration;
+        prepareForMediaRenderingStart_l();
         mPaused = true;
-        setPauseStartedTimeRealUs(ALooper::GetNowUs());
+        mMediaClock->setPlaybackRate(0.0);
     }
 
     mDrainAudioQueuePending = false;
@@ -1174,8 +1198,6 @@
 }
 
 void NuPlayer::Renderer::onResume() {
-    readProperties();
-
     if (!mPaused) {
         return;
     }
@@ -1185,17 +1207,14 @@
         mAudioSink->start();
     }
 
-    Mutex::Autolock autoLock(mLock);
-    mPaused = false;
-    if (mPauseStartedTimeRealUs != -1) {
-        int64_t newAnchorRealUs =
-            mAnchorTimeRealUs + ALooper::GetNowUs() - mPauseStartedTimeRealUs;
-        setAnchorTime(
-                mAnchorTimeMediaUs, newAnchorRealUs, mAnchorNumFramesWritten, true /* resume */);
-    }
+    {
+        Mutex::Autolock autoLock(mLock);
+        mPaused = false;
+        mMediaClock->setPlaybackRate(mPlaybackRate);
 
-    if (!mAudioQueue.empty()) {
-        postDrainAudioQueue_l();
+        if (!mAudioQueue.empty()) {
+            postDrainAudioQueue_l();
+        }
     }
 
     if (!mVideoQueue.empty()) {
@@ -1210,6 +1229,21 @@
     mVideoScheduler->init(fps);
 }
 
+int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
+    Mutex::Autolock autoLock(mLock);
+    return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
+}
+
+int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
+    Mutex::Autolock autoLock(mLock);
+    return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
+}
+
+bool NuPlayer::Renderer::getSyncQueues() {
+    Mutex::Autolock autoLock(mLock);
+    return mSyncQueues;
+}
+
 // TODO: Remove unnecessary calls to getPlayedOutAudioDurationUs()
 // as it acquires locks and may query the audio driver.
 //
@@ -1217,6 +1251,7 @@
 // accessing getTimestamp() or getPosition() every time a data buffer with
 // a media time is received.
 //
+// Calculate duration of played samples if played at normal rate (i.e., 1.0).
 int64_t NuPlayer::Renderer::getPlayedOutAudioDurationUs(int64_t nowUs) {
     uint32_t numFramesPlayed;
     int64_t numFramesPlayedAt;
@@ -1254,9 +1289,8 @@
         //ALOGD("getPosition: %d %lld", numFramesPlayed, numFramesPlayedAt);
     }
 
-    // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
     //CHECK_EQ(numFramesPlayed & (1 << 31), 0);  // can't be negative until 12.4 hrs, test
-    int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000LL * mAudioSink->msecsPerFrame())
+    int64_t durationUs = getDurationUsIfPlayedAtSampleRate(numFramesPlayed)
             + nowUs - numFramesPlayedAt;
     if (durationUs < 0) {
         // Occurs when numFramesPlayed position is very small and the following:
@@ -1297,19 +1331,21 @@
 
 void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
     if (offloadingAudio()) {
-        sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, id());
-        msg->setInt32("generation", mAudioOffloadPauseTimeoutGeneration);
+        mWakeLock->acquire();
+        sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, this);
+        msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
         msg->post(kOffloadPauseMaxUs);
     }
 }
 
 void NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() {
     if (offloadingAudio()) {
+        mWakeLock->release(true);
         ++mAudioOffloadPauseTimeoutGeneration;
     }
 }
 
-bool NuPlayer::Renderer::onOpenAudioSink(
+status_t NuPlayer::Renderer::onOpenAudioSink(
         const sp<AMessage> &format,
         bool offloadOnly,
         bool hasVideo,
@@ -1371,8 +1407,10 @@
             if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
                 ALOGV("openAudioSink: no change in offload mode");
                 // no change from previous configuration, everything ok.
-                return offloadingAudio();
+                return OK;
             }
+            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
+
             ALOGV("openAudioSink: try to open AudioSink in offload mode");
             uint32_t offloadFlags = flags;
             offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
@@ -1391,6 +1429,10 @@
                     &offloadInfo);
 
             if (err == OK) {
+                if (mPlaybackRate != 1.0) {
+                    mAudioSink->setPlaybackRatePermille(
+                            (int32_t)(mPlaybackRate * 1000 + 0.5f));
+                }
                 // If the playback is offloaded to h/w, we pass
                 // the HAL some metadata information.
                 // We don't want to do this for PCM because it
@@ -1414,10 +1456,24 @@
         ALOGV("openAudioSink: open AudioSink in NON-offload mode");
         uint32_t pcmFlags = flags;
         pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+
+        const PcmInfo info = {
+                (audio_channel_mask_t)channelMask,
+                (audio_output_flags_t)pcmFlags,
+                AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
+                numChannels,
+                sampleRate
+        };
+        if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
+            ALOGV("openAudioSink: no change in pcm mode");
+            // no change from previous configuration, everything ok.
+            return OK;
+        }
+
         audioSinkChanged = true;
         mAudioSink->close();
         mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
-        CHECK_EQ(mAudioSink->open(
+        status_t err = mAudioSink->open(
                     sampleRate,
                     numChannels,
                     (audio_channel_mask_t)channelMask,
@@ -1425,20 +1481,32 @@
                     8 /* bufferCount */,
                     NULL,
                     NULL,
-                    (audio_output_flags_t)pcmFlags),
-                 (status_t)OK);
+                    (audio_output_flags_t)pcmFlags);
+        if (err != OK) {
+            ALOGW("openAudioSink: non offloaded open failed status: %d", err);
+            mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
+            return err;
+        }
+        mCurrentPcmInfo = info;
+        if (mPlaybackRate != 1.0) {
+            mAudioSink->setPlaybackRatePermille(
+                    (int32_t)(mPlaybackRate * 1000 + 0.5f));
+        }
         mAudioSink->start();
     }
     if (audioSinkChanged) {
         onAudioSinkChanged();
     }
-
-    return offloadingAudio();
+    if (offloadingAudio()) {
+        mAudioOffloadTornDown = false;
+    }
+    return OK;
 }
 
 void NuPlayer::Renderer::onCloseAudioSink() {
     mAudioSink->close();
     mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
+    mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
 }
 
 }  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 7b46a59..38843d5 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -23,6 +23,8 @@
 namespace android {
 
 struct ABuffer;
+class  AWakeLock;
+struct MediaClock;
 struct VideoFrameScheduler;
 
 struct NuPlayer::Renderer : public AHandler {
@@ -46,37 +48,31 @@
 
     void queueEOS(bool audio, status_t finalResult);
 
-    void flush(bool audio);
+    void setPlaybackRate(float rate);
+
+    void flush(bool audio, bool notifyComplete);
 
     void signalTimeDiscontinuity();
 
     void signalAudioSinkChanged();
 
     void signalDisableOffloadAudio();
+    void signalEnableOffloadAudio();
 
     void pause();
     void resume();
 
     void setVideoFrameRate(float fps);
 
-    // Following setters and getters are protected by mTimeLock.
     status_t getCurrentPosition(int64_t *mediaUs);
-    status_t getCurrentPosition(
-            int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
-    void setHasMedia(bool audio);
-    void setAudioFirstAnchorTime(int64_t mediaUs);
-    void setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs);
-    void setAnchorTime(
-            int64_t mediaUs, int64_t realUs, int64_t numFramesWritten = -1, bool resume = false);
-    void setVideoLateByUs(int64_t lateUs);
     int64_t getVideoLateByUs();
-    void setPauseStartedTimeRealUs(int64_t realUs);
 
-    bool openAudioSink(
+    status_t openAudioSink(
             const sp<AMessage> &format,
             bool offloadOnly,
             bool hasVideo,
-            uint32_t flags);
+            uint32_t flags,
+            bool *isOffloaded);
     void closeAudioSink();
 
     enum {
@@ -106,14 +102,15 @@
         kWhatPostDrainVideoQueue = 'pDVQ',
         kWhatQueueBuffer         = 'queB',
         kWhatQueueEOS            = 'qEOS',
+        kWhatSetRate             = 'setR',
         kWhatFlush               = 'flus',
-        kWhatAudioSinkChanged    = 'auSC',
         kWhatPause               = 'paus',
         kWhatResume              = 'resm',
         kWhatOpenAudioSink       = 'opnA',
         kWhatCloseAudioSink      = 'clsA',
         kWhatStopAudioSink       = 'stpA',
         kWhatDisableOffloadAudio = 'noOA',
+        kWhatEnableOffloadAudio  = 'enOA',
         kWhatSetVideoFrameRate   = 'sVFR',
     };
 
@@ -140,30 +137,26 @@
     bool mDrainVideoQueuePending;
     int32_t mAudioQueueGeneration;
     int32_t mVideoQueueGeneration;
+    int32_t mAudioDrainGeneration;
+    int32_t mVideoDrainGeneration;
 
-    Mutex mTimeLock;
-    // |mTimeLock| protects the following 7 member vars that are related to time.
-    // Note: those members are only written on Renderer thread, so reading on Renderer thread
-    // doesn't need to be protected. Otherwise accessing those members must be protected by
-    // |mTimeLock|.
-    // TODO: move those members to a seperated media clock class.
+    sp<MediaClock> mMediaClock;
+    float mPlaybackRate;
     int64_t mAudioFirstAnchorTimeMediaUs;
     int64_t mAnchorTimeMediaUs;
-    int64_t mAnchorTimeRealUs;
     int64_t mAnchorNumFramesWritten;
-    int64_t mAnchorMaxMediaUs;
     int64_t mVideoLateByUs;
     bool mHasAudio;
     bool mHasVideo;
-    int64_t mPauseStartedTimeRealUs;
 
-    Mutex mFlushLock;  // protects the following 2 member vars.
-    bool mFlushingAudio;
-    bool mFlushingVideo;
+    bool mNotifyCompleteAudio;
+    bool mNotifyCompleteVideo;
 
     bool mSyncQueues;
 
+    // modified on only renderer's thread.
     bool mPaused;
+
     bool mVideoSampleReceived;
     bool mVideoRenderingStarted;
     int32_t mVideoRenderingStartGeneration;
@@ -175,9 +168,27 @@
     bool mAudioOffloadTornDown;
     audio_offload_info_t mCurrentOffloadInfo;
 
+    struct PcmInfo {
+        audio_channel_mask_t mChannelMask;
+        audio_output_flags_t mFlags;
+        audio_format_t mFormat;
+        int32_t mNumChannels;
+        int32_t mSampleRate;
+    };
+    PcmInfo mCurrentPcmInfo;
+    static const PcmInfo AUDIO_PCMINFO_INITIALIZER;
+
     int32_t mTotalBuffersQueued;
     int32_t mLastAudioBufferDrained;
 
+    sp<AWakeLock> mWakeLock;
+
+    status_t getCurrentPositionOnLooper(int64_t *mediaUs);
+    status_t getCurrentPositionOnLooper(
+            int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
+    bool getCurrentPositionIfPaused_l(int64_t *mediaUs);
+    status_t getCurrentPositionFromAnchor(
+            int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
 
     size_t fillAudioBuffer(void *buffer, size_t size);
 
@@ -186,25 +197,34 @@
     int64_t getPlayedOutAudioDurationUs(int64_t nowUs);
     void postDrainAudioQueue_l(int64_t delayUs = 0);
 
+    void clearAnchorTime_l();
+    void clearAudioFirstAnchorTime_l();
+    void setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs);
+    void setVideoLateByUs(int64_t lateUs);
+
     void onNewAudioMediaTime(int64_t mediaTimeUs);
     int64_t getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs);
 
     void onDrainVideoQueue();
     void postDrainVideoQueue();
 
-    void prepareForMediaRenderingStart();
-    void notifyIfMediaRenderingStarted();
+    void prepareForMediaRenderingStart_l();
+    void notifyIfMediaRenderingStarted_l();
 
     void onQueueBuffer(const sp<AMessage> &msg);
     void onQueueEOS(const sp<AMessage> &msg);
     void onFlush(const sp<AMessage> &msg);
     void onAudioSinkChanged();
     void onDisableOffloadAudio();
+    void onEnableOffloadAudio();
     void onPause();
     void onResume();
     void onSetVideoFrameRate(float fps);
+    int32_t getQueueGeneration(bool audio);
+    int32_t getDrainGeneration(bool audio);
+    bool getSyncQueues();
     void onAudioOffloadTearDown(AudioOffloadTearDownReason reason);
-    bool onOpenAudioSink(
+    status_t onOpenAudioSink(
             const sp<AMessage> &format,
             bool offloadOnly,
             bool hasVideo,
@@ -219,7 +239,7 @@
     void notifyAudioOffloadTearDown();
 
     void flushQueue(List<QueueEntry> *queue);
-    bool dropBufferWhileFlushing(bool audio, const sp<AMessage> &msg);
+    bool dropBufferIfStale(bool audio, const sp<AMessage> &msg);
     void syncQueuesDone_l();
 
     bool offloadingAudio() const { return (mFlags & FLAG_OFFLOAD_AUDIO) != 0; }
@@ -227,6 +247,8 @@
     void startAudioOffloadPauseTimeout();
     void cancelAudioOffloadPauseTimeout();
 
+    int64_t getDurationUsIfPlayedAtSampleRate(uint32_t numFrames);
+
     DISALLOW_EVIL_CONSTRUCTORS(Renderer);
 };
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 2f06c31..5a8beb1 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -28,7 +28,6 @@
 namespace android {
 
 struct ABuffer;
-struct MetaData;
 struct MediaBuffer;
 
 struct NuPlayer::Source : public AHandler {
@@ -39,6 +38,7 @@
         FLAG_CAN_SEEK           = 8,  // the "seek bar"
         FLAG_DYNAMIC_DURATION   = 16,
         FLAG_SECURE             = 32,
+        FLAG_PROTECTED          = 64,
     };
 
     enum {
@@ -48,6 +48,9 @@
         kWhatBufferingUpdate,
         kWhatBufferingStart,
         kWhatBufferingEnd,
+        kWhatPauseOnBufferingStart,
+        kWhatResumeOnBufferingEnd,
+        kWhatCacheStats,
         kWhatSubtitleData,
         kWhatTimedTextData,
         kWhatQueueDecoderShutdown,
@@ -97,7 +100,7 @@
         return INVALID_OPERATION;
     }
 
-    virtual status_t selectTrack(size_t /* trackIndex */, bool /* select */) {
+    virtual status_t selectTrack(size_t /* trackIndex */, bool /* select */, int64_t /* timeUs*/) {
         return INVALID_OPERATION;
     }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
index 885ebe4..f53afbd 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
@@ -29,9 +29,9 @@
 
 NuPlayer::NuPlayerStreamListener::NuPlayerStreamListener(
         const sp<IStreamSource> &source,
-        ALooper::handler_id id)
+        const sp<AHandler> &targetHandler)
     : mSource(source),
-      mTargetID(id),
+      mTargetHandler(targetHandler),
       mEOS(false),
       mSendDataNotification(true) {
     mSource->setListener(this);
@@ -65,8 +65,8 @@
     if (mSendDataNotification) {
         mSendDataNotification = false;
 
-        if (mTargetID != 0) {
-            (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+        if (mTargetHandler != NULL) {
+            (new AMessage(kWhatMoreDataQueued, mTargetHandler))->post();
         }
     }
 }
@@ -86,8 +86,8 @@
     if (mSendDataNotification) {
         mSendDataNotification = false;
 
-        if (mTargetID != 0) {
-            (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+        if (mTargetHandler != NULL) {
+            (new AMessage(kWhatMoreDataQueued, mTargetHandler))->post();
         }
     }
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h
index 1874d80..2de829b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h
@@ -29,7 +29,7 @@
 struct NuPlayer::NuPlayerStreamListener : public BnStreamListener {
     NuPlayerStreamListener(
             const sp<IStreamSource> &source,
-            ALooper::handler_id targetID);
+            const sp<AHandler> &targetHandler);
 
     virtual void queueBuffer(size_t index, size_t size);
 
@@ -59,7 +59,7 @@
     Mutex mLock;
 
     sp<IStreamSource> mSource;
-    ALooper::handler_id mTargetID;
+    sp<AHandler> mTargetHandler;
     sp<MemoryDealer> mMemoryDealer;
     Vector<sp<IMemory> > mBuffers;
     List<QueueEntry> mQueue;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 52ae9ee..5210fc8 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -50,7 +50,7 @@
       mState(DISCONNECTED),
       mFinalResult(OK),
       mDisconnectReplyID(0),
-      mBuffering(true),
+      mBuffering(false),
       mSeekGeneration(0),
       mEOSTimeoutAudio(0),
       mEOSTimeoutVideo(0) {
@@ -87,7 +87,7 @@
     CHECK(mHandler == NULL);
     CHECK(mSDPLoader == NULL);
 
-    sp<AMessage> notify = new AMessage(kWhatNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatNotify, this);
 
     CHECK_EQ(mState, (int)DISCONNECTED);
     mState = CONNECTING;
@@ -106,9 +106,7 @@
         mHandler->connect();
     }
 
-    sp<AMessage> notifyStart = dupNotify();
-    notifyStart->setInt32("what", kWhatBufferingStart);
-    notifyStart->post();
+    startBufferingIfNecessary();
 }
 
 void NuPlayer::RTSPSource::start() {
@@ -118,7 +116,7 @@
     if (mLooper == NULL) {
         return;
     }
-    sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
+    sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
 
     sp<AMessage> dummy;
     msg->postAndAwaitResponse(&dummy);
@@ -144,6 +142,7 @@
 }
 
 status_t NuPlayer::RTSPSource::feedMoreTSData() {
+    Mutex::Autolock _l(mBufferingLock);
     return mFinalResult;
 }
 
@@ -195,16 +194,8 @@
 
 status_t NuPlayer::RTSPSource::dequeueAccessUnit(
         bool audio, sp<ABuffer> *accessUnit) {
-    if (mBuffering) {
-        if (!haveSufficientDataOnAllTracks()) {
-            return -EWOULDBLOCK;
-        }
-
-        mBuffering = false;
-
-        sp<AMessage> notify = dupNotify();
-        notify->setInt32("what", kWhatBufferingEnd);
-        notify->post();
+    if (!stopBufferingIfNecessary()) {
+        return -EWOULDBLOCK;
     }
 
     sp<AnotherPacketSource> source = getSource(audio);
@@ -246,11 +237,7 @@
             if (!(otherSource != NULL && otherSource->isFinished(mediaDurationUs))) {
                 // We should not enter buffering mode
                 // if any of the sources already have detected EOS.
-                mBuffering = true;
-
-                sp<AMessage> notify = dupNotify();
-                notify->setInt32("what", kWhatBufferingStart);
-                notify->post();
+                startBufferingIfNecessary();
             }
 
             return -EWOULDBLOCK;
@@ -305,7 +292,7 @@
 }
 
 status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
-    sp<AMessage> msg = new AMessage(kWhatPerformSeek, id());
+    sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
     msg->setInt32("generation", ++mSeekGeneration);
     msg->setInt64("timeUs", seekTimeUs);
     msg->post(200000ll);
@@ -324,7 +311,7 @@
 
 void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
     if (msg->what() == kWhatDisconnect) {
-        uint32_t replyID;
+        sp<AReplyToken> replyID;
         CHECK(msg->senderAwaitsResponse(&replyID));
 
         mDisconnectReplyID = replyID;
@@ -613,7 +600,7 @@
             ALOGE("Unable to find url in SDP");
             err = UNKNOWN_ERROR;
         } else {
-            sp<AMessage> notify = new AMessage(kWhatNotify, id());
+            sp<AMessage> notify = new AMessage(kWhatNotify, this);
 
             mHandler = new MyHandler(rtspUri.c_str(), notify, mUIDValid, mUID);
             mLooper->registerHandler(mHandler);
@@ -630,7 +617,7 @@
         }
 
         mState = DISCONNECTED;
-        mFinalResult = err;
+        setError(err);
 
         if (mDisconnectReplyID != 0) {
             finishDisconnectIfPossible();
@@ -657,7 +644,7 @@
     }
 
     mState = DISCONNECTED;
-    mFinalResult = err;
+    setError(err);
 
     if (mDisconnectReplyID != 0) {
         finishDisconnectIfPossible();
@@ -678,4 +665,40 @@
     mDisconnectReplyID = 0;
 }
 
+void NuPlayer::RTSPSource::setError(status_t err) {
+    Mutex::Autolock _l(mBufferingLock);
+    mFinalResult = err;
+}
+
+void NuPlayer::RTSPSource::startBufferingIfNecessary() {
+    Mutex::Autolock _l(mBufferingLock);
+
+    if (!mBuffering) {
+        mBuffering = true;
+
+        sp<AMessage> notify = dupNotify();
+        notify->setInt32("what", kWhatBufferingStart);
+        notify->post();
+    }
+}
+
+bool NuPlayer::RTSPSource::stopBufferingIfNecessary() {
+    Mutex::Autolock _l(mBufferingLock);
+
+    if (mBuffering) {
+        if (!haveSufficientDataOnAllTracks()) {
+            return false;
+        }
+
+        mBuffering = false;
+
+        sp<AMessage> notify = dupNotify();
+        notify->setInt32("what", kWhatBufferingEnd);
+        notify->post();
+    }
+
+    return true;
+}
+
+
 }  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index f1cae53..5f2cf33 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -25,6 +25,7 @@
 namespace android {
 
 struct ALooper;
+struct AReplyToken;
 struct AnotherPacketSource;
 struct MyHandler;
 struct SDPLoader;
@@ -96,7 +97,8 @@
     bool mIsSDP;
     State mState;
     status_t mFinalResult;
-    uint32_t mDisconnectReplyID;
+    sp<AReplyToken> mDisconnectReplyID;
+    Mutex mBufferingLock;
     bool mBuffering;
 
     sp<ALooper> mLooper;
@@ -126,6 +128,9 @@
     bool haveSufficientDataOnAllTracks();
 
     void setEOSTimeout(bool audio, int64_t timeout);
+    void setError(status_t err);
+    void startBufferingIfNecessary();
+    bool stopBufferingIfNecessary();
 
     DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
 };
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index 27f5159..0246b59 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -37,20 +37,33 @@
         const sp<IStreamSource> &source)
     : Source(notify),
       mSource(source),
-      mFinalResult(OK) {
+      mFinalResult(OK),
+      mBuffering(false) {
 }
 
 NuPlayer::StreamingSource::~StreamingSource() {
+    if (mLooper != NULL) {
+        mLooper->unregisterHandler(id());
+        mLooper->stop();
+    }
 }
 
 void NuPlayer::StreamingSource::prepareAsync() {
+    if (mLooper == NULL) {
+        mLooper = new ALooper;
+        mLooper->setName("streaming");
+        mLooper->start();
+
+        mLooper->registerHandler(this);
+    }
+
     notifyVideoSizeChanged();
     notifyFlagsChanged(0);
     notifyPrepared();
 }
 
 void NuPlayer::StreamingSource::start() {
-    mStreamListener = new NuPlayerStreamListener(mSource, 0);
+    mStreamListener = new NuPlayerStreamListener(mSource, NULL);
 
     uint32_t sourceFlags = mSource->flags();
 
@@ -62,13 +75,15 @@
     mTSParser = new ATSParser(parserFlags);
 
     mStreamListener->start();
+
+    postReadBuffer();
 }
 
 status_t NuPlayer::StreamingSource::feedMoreTSData() {
-    if (mFinalResult != OK) {
-        return mFinalResult;
-    }
+    return postReadBuffer();
+}
 
+void NuPlayer::StreamingSource::onReadBuffer() {
     for (int32_t i = 0; i < 50; ++i) {
         char buffer[188];
         sp<AMessage> extra;
@@ -77,7 +92,7 @@
         if (n == 0) {
             ALOGI("input data EOS reached.");
             mTSParser->signalEOS(ERROR_END_OF_STREAM);
-            mFinalResult = ERROR_END_OF_STREAM;
+            setError(ERROR_END_OF_STREAM);
             break;
         } else if (n == INFO_DISCONTINUITY) {
             int32_t type = ATSParser::DISCONTINUITY_TIME;
@@ -88,7 +103,8 @@
                         IStreamListener::kKeyDiscontinuityMask, &mask)) {
                 if (mask == 0) {
                     ALOGE("Client specified an illegal discontinuity type.");
-                    return ERROR_UNSUPPORTED;
+                    setError(ERROR_UNSUPPORTED);
+                    break;
                 }
 
                 type = mask;
@@ -97,7 +113,6 @@
             mTSParser->signalDiscontinuity(
                     (ATSParser::DiscontinuityType)type, extra);
         } else if (n < 0) {
-            CHECK_EQ(n, -EWOULDBLOCK);
             break;
         } else {
             if (buffer[0] == 0x00) {
@@ -128,22 +143,80 @@
                     ALOGE("TS Parser returned error %d", err);
 
                     mTSParser->signalEOS(err);
-                    mFinalResult = err;
+                    setError(err);
                     break;
                 }
             }
         }
     }
+}
 
+status_t NuPlayer::StreamingSource::postReadBuffer() {
+    {
+        Mutex::Autolock _l(mBufferingLock);
+        if (mFinalResult != OK) {
+            return mFinalResult;
+        }
+        if (mBuffering) {
+            return OK;
+        }
+        mBuffering = true;
+    }
+
+    (new AMessage(kWhatReadBuffer, this))->post();
     return OK;
 }
 
-sp<MetaData> NuPlayer::StreamingSource::getFormatMeta(bool audio) {
-    ATSParser::SourceType type =
-        audio ? ATSParser::AUDIO : ATSParser::VIDEO;
+bool NuPlayer::StreamingSource::haveSufficientDataOnAllTracks() {
+    // We're going to buffer at least 2 secs worth data on all tracks before
+    // starting playback (both at startup and after a seek).
 
-    sp<AnotherPacketSource> source =
-        static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+    static const int64_t kMinDurationUs = 2000000ll;
+
+    sp<AnotherPacketSource> audioTrack = getSource(true /*audio*/);
+    sp<AnotherPacketSource> videoTrack = getSource(false /*audio*/);
+
+    status_t err;
+    int64_t durationUs;
+    if (audioTrack != NULL
+            && (durationUs = audioTrack->getBufferedDurationUs(&err))
+                    < kMinDurationUs
+            && err == OK) {
+        ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
+              durationUs / 1E6);
+        return false;
+    }
+
+    if (videoTrack != NULL
+            && (durationUs = videoTrack->getBufferedDurationUs(&err))
+                    < kMinDurationUs
+            && err == OK) {
+        ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
+              durationUs / 1E6);
+        return false;
+    }
+
+    return true;
+}
+
+void NuPlayer::StreamingSource::setError(status_t err) {
+    Mutex::Autolock _l(mBufferingLock);
+    mFinalResult = err;
+}
+
+sp<AnotherPacketSource> NuPlayer::StreamingSource::getSource(bool audio) {
+    if (mTSParser == NULL) {
+        return NULL;
+    }
+
+    sp<MediaSource> source = mTSParser->getSource(
+            audio ? ATSParser::AUDIO : ATSParser::VIDEO);
+
+    return static_cast<AnotherPacketSource *>(source.get());
+}
+
+sp<MetaData> NuPlayer::StreamingSource::getFormatMeta(bool audio) {
+    sp<AnotherPacketSource> source = getSource(audio);
 
     if (source == NULL) {
         return NULL;
@@ -154,16 +227,16 @@
 
 status_t NuPlayer::StreamingSource::dequeueAccessUnit(
         bool audio, sp<ABuffer> *accessUnit) {
-    ATSParser::SourceType type =
-        audio ? ATSParser::AUDIO : ATSParser::VIDEO;
-
-    sp<AnotherPacketSource> source =
-        static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+    sp<AnotherPacketSource> source = getSource(audio);
 
     if (source == NULL) {
         return -EWOULDBLOCK;
     }
 
+    if (!haveSufficientDataOnAllTracks()) {
+        postReadBuffer();
+    }
+
     status_t finalResult;
     if (!source->hasBufferAvailable(&finalResult)) {
         return finalResult == OK ? -EWOULDBLOCK : finalResult;
@@ -186,5 +259,26 @@
     return mSource->flags() & IStreamSource::kFlagIsRealTimeData;
 }
 
+void NuPlayer::StreamingSource::onMessageReceived(
+        const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatReadBuffer:
+        {
+            onReadBuffer();
+
+            {
+                Mutex::Autolock _l(mBufferingLock);
+                mBuffering = false;
+            }
+            break;
+        }
+        default:
+        {
+            TRESPASS();
+        }
+    }
+}
+
+
 }  // namespace android
 
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.h b/media/libmediaplayerservice/nuplayer/StreamingSource.h
index 412b6c4..1f95f3c 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.h
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.h
@@ -25,6 +25,7 @@
 
 struct ABuffer;
 struct ATSParser;
+struct AnotherPacketSource;
 
 struct NuPlayer::StreamingSource : public NuPlayer::Source {
     StreamingSource(
@@ -43,14 +44,29 @@
 protected:
     virtual ~StreamingSource();
 
+    virtual void onMessageReceived(const sp<AMessage> &msg);
+
     virtual sp<MetaData> getFormatMeta(bool audio);
 
 private:
+    enum {
+        kWhatReadBuffer,
+    };
     sp<IStreamSource> mSource;
     status_t mFinalResult;
     sp<NuPlayerStreamListener> mStreamListener;
     sp<ATSParser> mTSParser;
 
+    bool mBuffering;
+    Mutex mBufferingLock;
+    sp<ALooper> mLooper;
+
+    void setError(status_t err);
+    sp<AnotherPacketSource> getSource(bool audio);
+    bool haveSufficientDataOnAllTracks();
+    status_t postReadBuffer();
+    void onReadBuffer();
+
     DISALLOW_EVIL_CONSTRUCTORS(StreamingSource);
 };
 
diff --git a/media/libmediaplayerservice/tests/Android.mk b/media/libmediaplayerservice/tests/Android.mk
new file mode 100644
index 0000000..7bc78ff
--- /dev/null
+++ b/media/libmediaplayerservice/tests/Android.mk
@@ -0,0 +1,24 @@
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := DrmSessionManager_test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+	DrmSessionManager_test.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+	liblog \
+	libmediaplayerservice \
+	libutils \
+
+LOCAL_C_INCLUDES := \
+	frameworks/av/include \
+	frameworks/av/media/libmediaplayerservice \
+
+LOCAL_32_BIT_ONLY := true
+
+include $(BUILD_NATIVE_TEST)
+
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
new file mode 100644
index 0000000..d3e760b
--- /dev/null
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -0,0 +1,249 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "DrmSessionManager_test"
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+
+#include "Drm.h"
+#include "DrmSessionClientInterface.h"
+#include "DrmSessionManager.h"
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/ProcessInfoInterface.h>
+
+namespace android {
+
+struct FakeProcessInfo : public ProcessInfoInterface {
+    FakeProcessInfo() {}
+    virtual ~FakeProcessInfo() {}
+
+    virtual bool getPriority(int pid, int* priority) {
+        // For testing, use pid as priority.
+        // Lower the value higher the priority.
+        *priority = pid;
+        return true;
+    }
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
+};
+
+struct FakeDrm : public DrmSessionClientInterface {
+    FakeDrm() {}
+    virtual ~FakeDrm() {}
+
+    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
+        mReclaimedSessions.push_back(sessionId);
+        return true;
+    }
+
+    const Vector<Vector<uint8_t> >& reclaimedSessions() const {
+        return mReclaimedSessions;
+    }
+
+private:
+    Vector<Vector<uint8_t> > mReclaimedSessions;
+
+    DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
+};
+
+static const int kTestPid1 = 30;
+static const int kTestPid2 = 20;
+static const uint8_t kTestSessionId1[] = {1, 2, 3};
+static const uint8_t kTestSessionId2[] = {4, 5, 6, 7, 8};
+static const uint8_t kTestSessionId3[] = {9, 0};
+
+class DrmSessionManagerTest : public ::testing::Test {
+public:
+    DrmSessionManagerTest()
+        : mDrmSessionManager(new DrmSessionManager(new FakeProcessInfo())),
+          mTestDrm1(new FakeDrm()),
+          mTestDrm2(new FakeDrm()) {
+        GetSessionId(kTestSessionId1, ARRAY_SIZE(kTestSessionId1), &mSessionId1);
+        GetSessionId(kTestSessionId2, ARRAY_SIZE(kTestSessionId2), &mSessionId2);
+        GetSessionId(kTestSessionId3, ARRAY_SIZE(kTestSessionId3), &mSessionId3);
+    }
+
+protected:
+    static void GetSessionId(const uint8_t* ids, size_t num, Vector<uint8_t>* sessionId) {
+        for (size_t i = 0; i < num; ++i) {
+            sessionId->push_back(ids[i]);
+        }
+    }
+
+    static void ExpectEqSessionInfo(const SessionInfo& info, sp<DrmSessionClientInterface> drm,
+            const Vector<uint8_t>& sessionId, int64_t timeStamp) {
+        EXPECT_EQ(drm, info.drm);
+        EXPECT_TRUE(isEqualSessionId(sessionId, info.sessionId));
+        EXPECT_EQ(timeStamp, info.timeStamp);
+    }
+
+    void addSession() {
+        mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mSessionId1);
+        mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId2);
+        mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId3);
+        const PidSessionInfosMap& map = sessionMap();
+        EXPECT_EQ(2, map.size());
+        ssize_t index1 = map.indexOfKey(kTestPid1);
+        ASSERT_GE(index1, 0);
+        const SessionInfos& infos1 = map[index1];
+        EXPECT_EQ(1, infos1.size());
+        ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 0);
+
+        ssize_t index2 = map.indexOfKey(kTestPid2);
+        ASSERT_GE(index2, 0);
+        const SessionInfos& infos2 = map[index2];
+        EXPECT_EQ(2, infos2.size());
+        ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId2, 1);
+        ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 2);
+    }
+
+    const PidSessionInfosMap& sessionMap() {
+        return mDrmSessionManager->mSessionMap;
+    }
+
+    void testGetLowestPriority() {
+        int pid;
+        int priority;
+        EXPECT_FALSE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
+
+        addSession();
+        EXPECT_TRUE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
+
+        EXPECT_EQ(kTestPid1, pid);
+        FakeProcessInfo processInfo;
+        int priority1;
+        processInfo.getPriority(kTestPid1, &priority1);
+        EXPECT_EQ(priority1, priority);
+    }
+
+    void testGetLeastUsedSession() {
+        sp<DrmSessionClientInterface> drm;
+        Vector<uint8_t> sessionId;
+        EXPECT_FALSE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
+
+        addSession();
+
+        EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
+        EXPECT_EQ(mTestDrm1, drm);
+        EXPECT_TRUE(isEqualSessionId(mSessionId1, sessionId));
+
+        EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
+        EXPECT_EQ(mTestDrm2, drm);
+        EXPECT_TRUE(isEqualSessionId(mSessionId2, sessionId));
+
+        // mSessionId2 is no longer the least used session.
+        mDrmSessionManager->useSession(mSessionId2);
+        EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
+        EXPECT_EQ(mTestDrm2, drm);
+        EXPECT_TRUE(isEqualSessionId(mSessionId3, sessionId));
+    }
+
+    sp<DrmSessionManager> mDrmSessionManager;
+    sp<FakeDrm> mTestDrm1;
+    sp<FakeDrm> mTestDrm2;
+    Vector<uint8_t> mSessionId1;
+    Vector<uint8_t> mSessionId2;
+    Vector<uint8_t> mSessionId3;
+};
+
+TEST_F(DrmSessionManagerTest, addSession) {
+    addSession();
+}
+
+TEST_F(DrmSessionManagerTest, useSession) {
+    addSession();
+
+    mDrmSessionManager->useSession(mSessionId1);
+    mDrmSessionManager->useSession(mSessionId3);
+
+    const PidSessionInfosMap& map = sessionMap();
+    const SessionInfos& infos1 = map.valueFor(kTestPid1);
+    const SessionInfos& infos2 = map.valueFor(kTestPid2);
+    ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 3);
+    ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 4);
+}
+
+TEST_F(DrmSessionManagerTest, removeSession) {
+    addSession();
+
+    mDrmSessionManager->removeSession(mSessionId2);
+
+    const PidSessionInfosMap& map = sessionMap();
+    EXPECT_EQ(2, map.size());
+    const SessionInfos& infos1 = map.valueFor(kTestPid1);
+    const SessionInfos& infos2 = map.valueFor(kTestPid2);
+    EXPECT_EQ(1, infos1.size());
+    EXPECT_EQ(1, infos2.size());
+    // mSessionId2 has been removed.
+    ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId3, 2);
+}
+
+TEST_F(DrmSessionManagerTest, removeDrm) {
+    addSession();
+
+    sp<FakeDrm> drm = new FakeDrm;
+    const uint8_t ids[] = {123};
+    Vector<uint8_t> sessionId;
+    GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
+    mDrmSessionManager->addSession(kTestPid2, drm, sessionId);
+
+    mDrmSessionManager->removeDrm(mTestDrm2);
+
+    const PidSessionInfosMap& map = sessionMap();
+    const SessionInfos& infos2 = map.valueFor(kTestPid2);
+    EXPECT_EQ(1, infos2.size());
+    // mTestDrm2 has been removed.
+    ExpectEqSessionInfo(infos2[0], drm, sessionId, 3);
+}
+
+TEST_F(DrmSessionManagerTest, reclaimSession) {
+    EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
+    addSession();
+
+    // calling pid priority is too low
+    EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
+
+    EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
+    EXPECT_EQ(1, mTestDrm1->reclaimedSessions().size());
+    EXPECT_TRUE(isEqualSessionId(mSessionId1, mTestDrm1->reclaimedSessions()[0]));
+
+    mDrmSessionManager->removeSession(mSessionId1);
+
+    // add a session from a higher priority process.
+    sp<FakeDrm> drm = new FakeDrm;
+    const uint8_t ids[] = {1, 3, 5};
+    Vector<uint8_t> sessionId;
+    GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
+    mDrmSessionManager->addSession(15, drm, sessionId);
+
+    EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
+    EXPECT_EQ(1, mTestDrm2->reclaimedSessions().size());
+    // mSessionId2 is reclaimed.
+    EXPECT_TRUE(isEqualSessionId(mSessionId2, mTestDrm2->reclaimedSessions()[0]));
+}
+
+TEST_F(DrmSessionManagerTest, getLowestPriority) {
+    testGetLowestPriority();
+}
+
+TEST_F(DrmSessionManagerTest, getLeastUsedSession_l) {
+    testGetLeastUsedSession();
+}
+
+} // namespace android
diff --git a/media/libnbaio/Android.mk b/media/libnbaio/Android.mk
index 9707c4a..1353f28 100644
--- a/media/libnbaio/Android.mk
+++ b/media/libnbaio/Android.mk
@@ -11,7 +11,6 @@
     MonoPipeReader.cpp              \
     Pipe.cpp                        \
     PipeReader.cpp                  \
-    roundup.c                       \
     SourceAudioBufferProvider.cpp
 
 LOCAL_SRC_FILES += NBLog.cpp
@@ -27,12 +26,13 @@
 LOCAL_MODULE := libnbaio
 
 LOCAL_SHARED_LIBRARIES := \
+    libaudioutils \
     libbinder \
     libcommon_time_client \
     libcutils \
     libutils \
     liblog
 
-LOCAL_STATIC_LIBRARIES += libinstantssq
+LOCAL_C_INCLUDES := $(call include-path-for, audio-utils)
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libnbaio/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp
index 0b65861..129e9ef 100644
--- a/media/libnbaio/MonoPipe.cpp
+++ b/media/libnbaio/MonoPipe.cpp
@@ -27,7 +27,7 @@
 #include <utils/Trace.h>
 #include <media/AudioBufferProvider.h>
 #include <media/nbaio/MonoPipe.h>
-#include <media/nbaio/roundup.h>
+#include <audio_utils/roundup.h>
 
 
 namespace android {
diff --git a/media/libnbaio/Pipe.cpp b/media/libnbaio/Pipe.cpp
index 6e0ec8c..13f211d 100644
--- a/media/libnbaio/Pipe.cpp
+++ b/media/libnbaio/Pipe.cpp
@@ -21,7 +21,7 @@
 #include <cutils/compiler.h>
 #include <utils/Log.h>
 #include <media/nbaio/Pipe.h>
-#include <media/nbaio/roundup.h>
+#include <audio_utils/roundup.h>
 
 namespace android {
 
diff --git a/media/libnbaio/roundup.c b/media/libnbaio/roundup.c
deleted file mode 100644
index 1d552d1..0000000
--- a/media/libnbaio/roundup.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2012 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 <media/nbaio/roundup.h>
-
-unsigned roundup(unsigned v)
-{
-    // __builtin_clz is undefined for zero input
-    if (v == 0) {
-        v = 1;
-    }
-    int lz = __builtin_clz((int) v);
-    unsigned rounded = ((unsigned) 0x80000000) >> lz;
-    // 0x800000001 and higher are actually rounded _down_ to prevent overflow
-    if (v > rounded && lz > 0) {
-        rounded <<= 1;
-    }
-    return rounded;
-}
diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp
index 353920e..9d90dbd 100644
--- a/media/libstagefright/AACWriter.cpp
+++ b/media/libstagefright/AACWriter.cpp
@@ -36,32 +36,19 @@
 
 namespace android {
 
-AACWriter::AACWriter(const char *filename)
-    : mFd(-1),
-      mInitCheck(NO_INIT),
-      mStarted(false),
-      mPaused(false),
-      mResumed(false),
-      mChannelCount(-1),
-      mSampleRate(-1),
-      mAACProfile(OMX_AUDIO_AACObjectLC) {
-
-    ALOGV("AACWriter Constructor");
-
-    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
-    if (mFd >= 0) {
-        mInitCheck = OK;
-    }
-}
-
 AACWriter::AACWriter(int fd)
     : mFd(dup(fd)),
       mInitCheck(mFd < 0? NO_INIT: OK),
       mStarted(false),
       mPaused(false),
       mResumed(false),
+      mThread(0),
+      mEstimatedSizeBytes(0),
+      mEstimatedDurationUs(0),
       mChannelCount(-1),
-      mSampleRate(-1) {
+      mSampleRate(-1),
+      mAACProfile(OMX_AUDIO_AACObjectLC),
+      mFrameDurationUs(0) {
 }
 
 AACWriter::~AACWriter() {
@@ -79,10 +66,6 @@
     return mInitCheck;
 }
 
-static int writeInt8(int fd, uint8_t x) {
-    return ::write(fd, &x, 1);
-}
-
 
 status_t AACWriter::addSource(const sp<MediaSource> &source) {
     if (mInitCheck != OK) {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 4c8a199..31e10ce 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -419,6 +419,7 @@
       mMetaDataBuffersToSubmit(0),
       mRepeatFrameDelayUs(-1ll),
       mMaxPtsGapUs(-1ll),
+      mMaxFps(-1),
       mTimePerFrameUs(-1ll),
       mTimePerCaptureUs(-1ll),
       mCreateInputBuffersSuspended(false),
@@ -451,61 +452,61 @@
 
 void ACodec::initiateSetup(const sp<AMessage> &msg) {
     msg->setWhat(kWhatSetup);
-    msg->setTarget(id());
+    msg->setTarget(this);
     msg->post();
 }
 
 void ACodec::signalSetParameters(const sp<AMessage> &params) {
-    sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
+    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
     msg->setMessage("params", params);
     msg->post();
 }
 
 void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
     msg->setWhat(kWhatAllocateComponent);
-    msg->setTarget(id());
+    msg->setTarget(this);
     msg->post();
 }
 
 void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
     msg->setWhat(kWhatConfigureComponent);
-    msg->setTarget(id());
+    msg->setTarget(this);
     msg->post();
 }
 
 void ACodec::initiateCreateInputSurface() {
-    (new AMessage(kWhatCreateInputSurface, id()))->post();
+    (new AMessage(kWhatCreateInputSurface, this))->post();
 }
 
 void ACodec::signalEndOfInputStream() {
-    (new AMessage(kWhatSignalEndOfInputStream, id()))->post();
+    (new AMessage(kWhatSignalEndOfInputStream, this))->post();
 }
 
 void ACodec::initiateStart() {
-    (new AMessage(kWhatStart, id()))->post();
+    (new AMessage(kWhatStart, this))->post();
 }
 
 void ACodec::signalFlush() {
     ALOGV("[%s] signalFlush", mComponentName.c_str());
-    (new AMessage(kWhatFlush, id()))->post();
+    (new AMessage(kWhatFlush, this))->post();
 }
 
 void ACodec::signalResume() {
-    (new AMessage(kWhatResume, id()))->post();
+    (new AMessage(kWhatResume, this))->post();
 }
 
 void ACodec::initiateShutdown(bool keepComponentAllocated) {
-    sp<AMessage> msg = new AMessage(kWhatShutdown, id());
+    sp<AMessage> msg = new AMessage(kWhatShutdown, this);
     msg->setInt32("keepComponentAllocated", keepComponentAllocated);
     msg->post();
     if (!keepComponentAllocated) {
         // ensure shutdown completes in 3 seconds
-        (new AMessage(kWhatReleaseCodecInstance, id()))->post(3000000);
+        (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000);
     }
 }
 
 void ACodec::signalRequestIDRFrame() {
-    (new AMessage(kWhatRequestIDRFrame, id()))->post();
+    (new AMessage(kWhatRequestIDRFrame, this))->post();
 }
 
 // *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
@@ -516,7 +517,7 @@
 void ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() {
     if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
             mMetaDataBuffersToSubmit > 0) {
-        (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, id()))->post();
+        (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, this))->post();
     }
 }
 
@@ -669,8 +670,9 @@
         // XXX: Currently this error is logged, but not fatal.
         usage = 0;
     }
+    int omxUsage = usage;
 
-    if (mFlags & kFlagIsSecure) {
+    if (mFlags & kFlagIsGrallocUsageProtected) {
         usage |= GRALLOC_USAGE_PROTECTED;
     }
 
@@ -693,6 +695,18 @@
         }
     }
 
+    int consumerUsage = 0;
+    err = mNativeWindow->query(
+            mNativeWindow.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS,
+            &consumerUsage);
+    if (err != 0) {
+        ALOGW("failed to get consumer usage bits. ignoring");
+        err = 0;
+    }
+
+    ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec) + %#x(Consumer) = %#x",
+            omxUsage, usage, consumerUsage, usage | consumerUsage);
+    usage |= consumerUsage;
     err = native_window_set_usage(
             mNativeWindow.get(),
             usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
@@ -922,7 +936,6 @@
 
 ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
     ANativeWindowBuffer *buf;
-    int fenceFd = -1;
     CHECK(mNativeWindow.get() != NULL);
 
     if (mTunneled) {
@@ -1106,6 +1119,8 @@
             "video_decoder.mpeg2", "video_encoder.mpeg2" },
         { MEDIA_MIMETYPE_AUDIO_AC3,
             "audio_decoder.ac3", "audio_encoder.ac3" },
+        { MEDIA_MIMETYPE_AUDIO_EAC3,
+            "audio_decoder.eac3", "audio_encoder.eac3" },
     };
 
     static const size_t kNumMimeToRole =
@@ -1158,7 +1173,7 @@
     }
 
     sp<AMessage> inputFormat = new AMessage();
-    sp<AMessage> outputFormat = new AMessage();
+    sp<AMessage> outputFormat = mNotify->dup(); // will use this for kWhatOutputFormatChanged
 
     mIsEncoder = encoder;
 
@@ -1245,6 +1260,10 @@
             mMaxPtsGapUs = -1ll;
         }
 
+        if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
+            mMaxFps = -1;
+        }
+
         if (!msg->findInt64("time-lapse", &mTimePerCaptureUs)) {
             mTimePerCaptureUs = -1ll;
         }
@@ -1256,18 +1275,47 @@
         }
     }
 
+    // NOTE: we only use native window for video decoders
     sp<RefBase> obj;
-    int32_t haveNativeWindow = msg->findObject("native-window", &obj) &&
-        obj != NULL;
+    bool haveNativeWindow = msg->findObject("native-window", &obj)
+            && obj != NULL && video && !encoder;
     mStoreMetaDataInOutputBuffers = false;
     if (video && !encoder) {
         inputFormat->setInt32("adaptive-playback", false);
+
+        int32_t usageProtected;
+        if (msg->findInt32("protected", &usageProtected) && usageProtected) {
+            if (!haveNativeWindow) {
+                ALOGE("protected output buffers must be sent to an ANativeWindow");
+                return PERMISSION_DENIED;
+            }
+            mFlags |= kFlagIsGrallocUsageProtected;
+            mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
+        }
     }
-    if (!encoder && video && haveNativeWindow) {
+    if (haveNativeWindow) {
         sp<NativeWindowWrapper> windowWrapper(
                 static_cast<NativeWindowWrapper *>(obj.get()));
         sp<ANativeWindow> nativeWindow = windowWrapper->getNativeWindow();
 
+        // START of temporary support for automatic FRC - THIS WILL BE REMOVED
+        int32_t autoFrc;
+        if (msg->findInt32("auto-frc", &autoFrc)) {
+            bool enabled = autoFrc;
+            OMX_CONFIG_BOOLEANTYPE config;
+            InitOMXParams(&config);
+            config.bEnabled = (OMX_BOOL)enabled;
+            status_t temp = mOMX->setConfig(
+                    mNode, (OMX_INDEXTYPE)OMX_IndexConfigAutoFramerateConversion,
+                    &config, sizeof(config));
+            if (temp == OK) {
+                outputFormat->setInt32("auto-frc", enabled);
+            } else if (enabled) {
+                ALOGI("codec does not support requested auto-frc (err %d)", temp);
+            }
+        }
+        // END of temporary support for automatic FRC
+
         int32_t tunneled;
         if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
             tunneled != 0) {
@@ -1285,11 +1333,36 @@
                 return err;
             }
 
-            inputFormat->setInt32("adaptive-playback", true);
+            int32_t maxWidth = 0, maxHeight = 0;
+            if (msg->findInt32("max-width", &maxWidth) &&
+                    msg->findInt32("max-height", &maxHeight)) {
+
+                err = mOMX->prepareForAdaptivePlayback(
+                        mNode, kPortIndexOutput, OMX_TRUE, maxWidth, maxHeight);
+                if (err != OK) {
+                    ALOGW("[%s] prepareForAdaptivePlayback failed w/ err %d",
+                            mComponentName.c_str(), err);
+                    // allow failure
+                    err = OK;
+                } else {
+                    inputFormat->setInt32("max-width", maxWidth);
+                    inputFormat->setInt32("max-height", maxHeight);
+                    inputFormat->setInt32("adaptive-playback", true);
+                }
+            }
         } else {
             ALOGV("Configuring CPU controlled video playback.");
             mTunneled = false;
 
+            // Explicity reset the sideband handle of the window for
+            // non-tunneled video in case the window was previously used
+            // for a tunneled video playback.
+            err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
+            if (err != OK) {
+                ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
+                return err;
+            }
+
             // Always try to enable dynamic output buffers on native surface
             err = mOMX->storeMetaDataInBuffers(
                     mNode, kPortIndexOutput, OMX_TRUE);
@@ -1364,10 +1437,79 @@
     }
 
     if (video) {
+        // determine need for software renderer
+        bool usingSwRenderer = false;
+        if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
+            usingSwRenderer = true;
+            haveNativeWindow = false;
+        }
+
         if (encoder) {
             err = setupVideoEncoder(mime, msg);
         } else {
-            err = setupVideoDecoder(mime, msg);
+            err = setupVideoDecoder(mime, msg, haveNativeWindow);
+        }
+
+        if (err != OK) {
+            return err;
+        }
+
+        if (haveNativeWindow) {
+            sp<NativeWindowWrapper> nativeWindow(
+                    static_cast<NativeWindowWrapper *>(obj.get()));
+            CHECK(nativeWindow != NULL);
+            mNativeWindow = nativeWindow->getNativeWindow();
+
+            native_window_set_scaling_mode(
+                    mNativeWindow.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+        }
+
+        // initialize native window now to get actual output format
+        // TODO: this is needed for some encoders even though they don't use native window
+        CHECK_EQ((status_t)OK, initNativeWindow());
+
+        // fallback for devices that do not handle flex-YUV for native buffers
+        if (haveNativeWindow) {
+            int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
+            if (msg->findInt32("color-format", &requestedColorFormat) &&
+                    requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
+                CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
+                int32_t colorFormat = OMX_COLOR_FormatUnused;
+                OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
+                CHECK(outputFormat->findInt32("color-format", &colorFormat));
+                ALOGD("[%s] Requested output format %#x and got %#x.",
+                        mComponentName.c_str(), requestedColorFormat, colorFormat);
+                if (!isFlexibleColorFormat(
+                                mOMX, mNode, colorFormat, haveNativeWindow, &flexibleEquivalent)
+                        || flexibleEquivalent != (OMX_U32)requestedColorFormat) {
+                    // device did not handle flex-YUV request for native window, fall back
+                    // to SW renderer
+                    ALOGI("[%s] Falling back to software renderer", mComponentName.c_str());
+                    mNativeWindow.clear();
+                    haveNativeWindow = false;
+                    usingSwRenderer = true;
+                    if (mStoreMetaDataInOutputBuffers) {
+                        err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_FALSE);
+                        mStoreMetaDataInOutputBuffers = false;
+                        // TODO: implement adaptive-playback support for bytebuffer mode.
+                        // This is done by SW codecs, but most HW codecs don't support it.
+                        inputFormat->setInt32("adaptive-playback", false);
+                    }
+                    if (err == OK) {
+                        err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
+                    }
+                    if (mFlags & kFlagIsGrallocUsageProtected) {
+                        // fallback is not supported for protected playback
+                        err = PERMISSION_DENIED;
+                    } else if (err == OK) {
+                        err = setupVideoDecoder(mime, msg, false);
+                    }
+                }
+            }
+        }
+
+        if (usingSwRenderer) {
+            outputFormat->setInt32("using-sw-renderer", 1);
         }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
         int32_t numChannels, sampleRate;
@@ -1498,6 +1640,15 @@
         } else {
             err = setupAC3Codec(encoder, numChannels, sampleRate);
         }
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
+        int32_t numChannels;
+        int32_t sampleRate;
+        if (!msg->findInt32("channel-count", &numChannels)
+                || !msg->findInt32("sample-rate", &sampleRate)) {
+            err = INVALID_OPERATION;
+        } else {
+            err = setupEAC3Codec(encoder, numChannels, sampleRate);
+        }
     }
 
     if (err != OK) {
@@ -1525,6 +1676,13 @@
         err = setMinBufferSize(kPortIndexInput, 8192);  // XXX
     }
 
+    int32_t priority;
+    if (msg->findInt32("priority", &priority)) {
+        err = setPriority(priority);
+    }
+
+    mBaseOutputFormat = outputFormat;
+
     CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
     CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
     mInputFormat = inputFormat;
@@ -1533,6 +1691,22 @@
     return err;
 }
 
+status_t ACodec::setPriority(int32_t priority) {
+    if (priority < 0) {
+        return BAD_VALUE;
+    }
+    OMX_PARAM_U32TYPE config;
+    InitOMXParams(&config);
+    config.nU32 = (OMX_U32)priority;
+    status_t temp = mOMX->setConfig(
+            mNode, (OMX_INDEXTYPE)OMX_IndexConfigPriority,
+            &config, sizeof(config));
+    if (temp != OK) {
+        ALOGI("codec does not support config priority (err %d)", temp);
+    }
+    return OK;
+}
+
 status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
@@ -1781,6 +1955,44 @@
             sizeof(def));
 }
 
+status_t ACodec::setupEAC3Codec(
+        bool encoder, int32_t numChannels, int32_t sampleRate) {
+    status_t err = setupRawAudioFormat(
+            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
+
+    if (err != OK) {
+        return err;
+    }
+
+    if (encoder) {
+        ALOGW("EAC3 encoding is not supported.");
+        return INVALID_OPERATION;
+    }
+
+    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexInput;
+
+    err = mOMX->getParameter(
+            mNode,
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
+            &def,
+            sizeof(def));
+
+    if (err != OK) {
+        return err;
+    }
+
+    def.nChannels = numChannels;
+    def.nSampleRate = sampleRate;
+
+    return mOMX->setParameter(
+            mNode,
+            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
+            &def,
+            sizeof(def));
+}
+
 static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(
         bool isAMRWB, int32_t bps) {
     if (isAMRWB) {
@@ -1961,7 +2173,8 @@
 status_t ACodec::setVideoPortFormatType(
         OMX_U32 portIndex,
         OMX_VIDEO_CODINGTYPE compressionFormat,
-        OMX_COLOR_FORMATTYPE colorFormat) {
+        OMX_COLOR_FORMATTYPE colorFormat,
+        bool usingNativeBuffers) {
     OMX_VIDEO_PARAM_PORTFORMATTYPE format;
     InitOMXParams(&format);
     format.nPortIndex = portIndex;
@@ -1981,10 +2194,10 @@
 
         // substitute back flexible color format to codec supported format
         OMX_U32 flexibleEquivalent;
-        if (compressionFormat == OMX_VIDEO_CodingUnused &&
-                isFlexibleColorFormat(
-                        mOMX, mNode, format.eColorFormat, &flexibleEquivalent) &&
-                colorFormat == flexibleEquivalent) {
+        if (compressionFormat == OMX_VIDEO_CodingUnused
+                && isFlexibleColorFormat(
+                        mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
+                && colorFormat == flexibleEquivalent) {
             ALOGI("[%s] using color format %#x in place of %#x",
                     mComponentName.c_str(), format.eColorFormat, colorFormat);
             colorFormat = format.eColorFormat;
@@ -2028,18 +2241,66 @@
     return err;
 }
 
-status_t ACodec::setSupportedOutputFormat() {
-    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+// Set optimal output format. OMX component lists output formats in the order
+// of preference, but this got more complicated since the introduction of flexible
+// YUV formats. We support a legacy behavior for applications that do not use
+// surface output, do not specify an output format, but expect a "usable" standard
+// OMX format. SW readable and standard formats must be flex-YUV.
+//
+// Suggested preference order:
+// - optimal format for texture rendering (mediaplayer behavior)
+// - optimal SW readable & texture renderable format (flex-YUV support)
+// - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
+// - legacy "usable" standard formats
+//
+// For legacy support, we prefer a standard format, but will settle for a SW readable
+// flex-YUV format.
+status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
+    OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
     InitOMXParams(&format);
     format.nPortIndex = kPortIndexOutput;
-    format.nIndex = 0;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoPortFormat,
-            &format, sizeof(format));
-    CHECK_EQ(err, (status_t)OK);
-    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
+    InitOMXParams(&legacyFormat);
+    // this field will change when we find a suitable legacy format
+    legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
 
+    for (OMX_U32 index = 0; ; ++index) {
+        format.nIndex = index;
+        status_t err = mOMX->getParameter(
+                mNode, OMX_IndexParamVideoPortFormat,
+                &format, sizeof(format));
+        if (err != OK) {
+            // no more formats, pick legacy format if found
+            if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
+                 memcpy(&format, &legacyFormat, sizeof(format));
+                 break;
+            }
+            return err;
+        }
+        if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
+            return OMX_ErrorBadParameter;
+        }
+        if (!getLegacyFlexibleFormat) {
+            break;
+        }
+        // standard formats that were exposed to users before
+        if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
+                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
+                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
+                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
+                || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
+            break;
+        }
+        // find best legacy non-standard format
+        OMX_U32 flexibleEquivalent;
+        if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
+                && isFlexibleColorFormat(
+                        mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
+                        &flexibleEquivalent)
+                && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
+            memcpy(&legacyFormat, &format, sizeof(format));
+        }
+    }
     return mOMX->setParameter(
             mNode, OMX_IndexParamVideoPortFormat,
             &format, sizeof(format));
@@ -2091,7 +2352,7 @@
 }
 
 status_t ACodec::setupVideoDecoder(
-        const char *mime, const sp<AMessage> &msg) {
+        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) {
     int32_t width, height;
     if (!msg->findInt32("width", &width)
             || !msg->findInt32("height", &height)) {
@@ -2117,22 +2378,31 @@
         OMX_COLOR_FORMATTYPE colorFormat =
             static_cast<OMX_COLOR_FORMATTYPE>(tmp);
         err = setVideoPortFormatType(
-                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat);
+                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
         if (err != OK) {
             ALOGW("[%s] does not support color format %d",
                   mComponentName.c_str(), colorFormat);
-            err = setSupportedOutputFormat();
+            err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
         }
     } else {
-        err = setSupportedOutputFormat();
+        err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
     }
 
     if (err != OK) {
         return err;
     }
 
+    int32_t frameRateInt;
+    float frameRateFloat;
+    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
+        if (!msg->findInt32("frame-rate", &frameRateInt)) {
+            frameRateInt = -1;
+        }
+        frameRateFloat = (float)frameRateInt;
+    }
+
     err = setVideoFormatOnPort(
-            kPortIndexInput, width, height, compressionFormat);
+            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
 
     if (err != OK) {
         return err;
@@ -2896,7 +3166,8 @@
 
 status_t ACodec::setVideoFormatOnPort(
         OMX_U32 portIndex,
-        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
+        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
+        float frameRate) {
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
@@ -2924,6 +3195,9 @@
     if (portIndex == kPortIndexInput) {
         video_def->eCompressionFormat = compressionFormat;
         video_def->eColorFormat = OMX_COLOR_FormatUnused;
+        if (frameRate >= 0) {
+            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
+        }
     }
 
     err = mOMX->setParameter(
@@ -3006,7 +3280,6 @@
 }
 
 void ACodec::deferMessage(const sp<AMessage> &msg) {
-    bool wasEmptyBefore = mDeferredQueue.empty();
     mDeferredQueue.push_back(msg);
 }
 
@@ -3036,7 +3309,8 @@
     if (fmt != OMX_COLOR_FormatYUV420Planar &&
         fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
         fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
-        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar) {
+        fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
+        fmt != HAL_PIXEL_FORMAT_YV12) {
         ALOGW("do not know color format 0x%x = %d", fmt, fmt);
         return false;
     }
@@ -3065,8 +3339,31 @@
     image.mPlane[image.Y].mHorizSubsampling = 1;
     image.mPlane[image.Y].mVertSubsampling = 1;
 
-    switch (fmt) {
-        case OMX_COLOR_FormatYUV420Planar: // used for YV12
+    switch ((int)fmt) {
+        case HAL_PIXEL_FORMAT_YV12:
+            if (params.bUsingNativeBuffers) {
+                size_t ystride = align(params.nStride, 16);
+                size_t cstride = align(params.nStride / 2, 16);
+                image.mPlane[image.Y].mRowInc = ystride;
+
+                image.mPlane[image.V].mOffset = ystride * params.nSliceHeight;
+                image.mPlane[image.V].mColInc = 1;
+                image.mPlane[image.V].mRowInc = cstride;
+                image.mPlane[image.V].mHorizSubsampling = 2;
+                image.mPlane[image.V].mVertSubsampling = 2;
+
+                image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset
+                        + (cstride * params.nSliceHeight / 2);
+                image.mPlane[image.U].mColInc = 1;
+                image.mPlane[image.U].mRowInc = cstride;
+                image.mPlane[image.U].mHorizSubsampling = 2;
+                image.mPlane[image.U].mVertSubsampling = 2;
+                break;
+            } else {
+                // fall through as YV12 is used for YUV420Planar by some codecs
+            }
+
+        case OMX_COLOR_FormatYUV420Planar:
         case OMX_COLOR_FormatYUV420PackedPlanar:
             image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
             image.mPlane[image.U].mColInc = 1;
@@ -3126,7 +3423,7 @@
 // static
 bool ACodec::isFlexibleColorFormat(
          const sp<IOMX> &omx, IOMX::node_id node,
-         uint32_t colorFormat, OMX_U32 *flexibleEquivalent) {
+         uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
     DescribeColorFormatParams describeParams;
     InitOMXParams(&describeParams);
     describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
@@ -3135,6 +3432,7 @@
     describeParams.nFrameHeight = 128;
     describeParams.nStride = 128;
     describeParams.nSliceHeight = 128;
+    describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
 
     CHECK(flexibleEquivalent != NULL);
 
@@ -3192,20 +3490,30 @@
                     notify->setInt32("slice-height", videoDef->nSliceHeight);
                     notify->setInt32("color-format", videoDef->eColorFormat);
 
-                    DescribeColorFormatParams describeParams;
-                    InitOMXParams(&describeParams);
-                    describeParams.eColorFormat = videoDef->eColorFormat;
-                    describeParams.nFrameWidth = videoDef->nFrameWidth;
-                    describeParams.nFrameHeight = videoDef->nFrameHeight;
-                    describeParams.nStride = videoDef->nStride;
-                    describeParams.nSliceHeight = videoDef->nSliceHeight;
+                    if (mNativeWindow == NULL) {
+                        DescribeColorFormatParams describeParams;
+                        InitOMXParams(&describeParams);
+                        describeParams.eColorFormat = videoDef->eColorFormat;
+                        describeParams.nFrameWidth = videoDef->nFrameWidth;
+                        describeParams.nFrameHeight = videoDef->nFrameHeight;
+                        describeParams.nStride = videoDef->nStride;
+                        describeParams.nSliceHeight = videoDef->nSliceHeight;
+                        describeParams.bUsingNativeBuffers = OMX_FALSE;
 
-                    if (describeColorFormat(mOMX, mNode, describeParams)) {
-                        notify->setBuffer(
-                                "image-data",
-                                ABuffer::CreateAsCopy(
-                                        &describeParams.sMediaImage,
-                                        sizeof(describeParams.sMediaImage)));
+                        if (describeColorFormat(mOMX, mNode, describeParams)) {
+                            notify->setBuffer(
+                                    "image-data",
+                                    ABuffer::CreateAsCopy(
+                                            &describeParams.sMediaImage,
+                                            sizeof(describeParams.sMediaImage)));
+
+                            MediaImage *img = &describeParams.sMediaImage;
+                            ALOGV("[%s] MediaImage { F(%zux%zu) @%zu+%zu+%zu @%zu+%zu+%zu @%zu+%zu+%zu }",
+                                    mComponentName.c_str(), img->mWidth, img->mHeight,
+                                    img->mPlane[0].mOffset, img->mPlane[0].mColInc, img->mPlane[0].mRowInc,
+                                    img->mPlane[1].mOffset, img->mPlane[1].mColInc, img->mPlane[1].mRowInc,
+                                    img->mPlane[2].mOffset, img->mPlane[2].mColInc, img->mPlane[2].mRowInc);
+                        }
                     }
 
                     if (portIndex != kPortIndexOutput) {
@@ -3302,9 +3610,12 @@
                     break;
                 }
             }
-
             notify->setInt32("width", videoDef->nFrameWidth);
             notify->setInt32("height", videoDef->nFrameHeight);
+            ALOGV("[%s] %s format is %s", mComponentName.c_str(),
+                    portIndex == kPortIndexInput ? "input" : "output",
+                    notify->debugString().c_str());
+
             break;
         }
 
@@ -3456,6 +3767,24 @@
                     break;
                 }
 
+                case OMX_AUDIO_CodingAndroidEAC3:
+                {
+                    OMX_AUDIO_PARAM_ANDROID_EAC3TYPE params;
+                    InitOMXParams(&params);
+                    params.nPortIndex = portIndex;
+
+                    CHECK_EQ((status_t)OK, mOMX->getParameter(
+                            mNode,
+                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
+                            &params,
+                            sizeof(params)));
+
+                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
+                    notify->setInt32("channel-count", params.nChannels);
+                    notify->setInt32("sample-rate", params.nSampleRate);
+                    break;
+                }
+
                 case OMX_AUDIO_CodingAndroidOPUS:
                 {
                     OMX_AUDIO_PARAM_ANDROID_OPUSTYPE params;
@@ -3500,6 +3829,23 @@
                     break;
                 }
 
+                case OMX_AUDIO_CodingGSMFR:
+                {
+                    OMX_AUDIO_PARAM_MP3TYPE params;
+                    InitOMXParams(&params);
+                    params.nPortIndex = portIndex;
+
+                    CHECK_EQ(mOMX->getParameter(
+                                mNode, OMX_IndexParamAudioPcm,
+                                &params, sizeof(params)),
+                             (status_t)OK);
+
+                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
+                    notify->setInt32("channel-count", params.nChannels);
+                    notify->setInt32("sample-rate", params.nSampleRate);
+                    break;
+                }
+
                 default:
                     ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
                     TRESPASS();
@@ -3515,7 +3861,7 @@
 }
 
 void ACodec::sendFormatChange(const sp<AMessage> &reply) {
-    sp<AMessage> notify = mNotify->dup();
+    sp<AMessage> notify = mBaseOutputFormat->dup();
     notify->setInt32("what", kWhatOutputFormatChanged);
 
     CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
@@ -3641,7 +3987,6 @@
     // on the screen and then been replaced, so an previous video frames are
     // guaranteed NOT to be currently displayed.
     for (int i = 0; i < numBufs + 1; i++) {
-        int fenceFd = -1;
         err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
         if (err != NO_ERROR) {
             ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
@@ -3974,7 +4319,7 @@
     info->mData->meta()->clear();
     notify->setBuffer("buffer", info->mData);
 
-    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
+    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec);
     reply->setInt32("buffer-id", info->mBufferID);
 
     notify->setMessage("reply", reply);
@@ -4220,7 +4565,8 @@
 
         case RESUBMIT_BUFFERS:
         {
-            if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
+            if (rangeLength == 0 && (!(flags & OMX_BUFFERFLAG_EOS)
+                    || mCodec->mPortEOS[kPortIndexOutput])) {
                 ALOGV("[%s] calling fillBuffer %u",
                      mCodec->mComponentName.c_str(), info->mBufferID);
 
@@ -4233,7 +4579,7 @@
             }
 
             sp<AMessage> reply =
-                new AMessage(kWhatOutputBufferDrained, mCodec->id());
+                new AMessage(kWhatOutputBufferDrained, mCodec);
 
             if (!mCodec->mSentFormat && rangeLength > 0) {
                 mCodec->sendFormatChange(reply);
@@ -4419,7 +4765,7 @@
     ALOGV("Now uninitialized");
 
     if (mDeathNotifier != NULL) {
-        mCodec->mOMX->asBinder()->unlinkToDeath(mDeathNotifier);
+        IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
         mDeathNotifier.clear();
     }
 
@@ -4509,10 +4855,10 @@
 
     sp<IOMX> omx = client.interface();
 
-    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec->id());
+    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);
 
     mDeathNotifier = new DeathNotifier(notify);
-    if (omx->asBinder()->linkToDeath(mDeathNotifier) != OK) {
+    if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) {
         // This was a local binder, if it dies so do we, we won't care
         // about any notifications in the afterlife.
         mDeathNotifier.clear();
@@ -4584,7 +4930,7 @@
         return false;
     }
 
-    notify = new AMessage(kWhatOMXMessage, mCodec->id());
+    notify = new AMessage(kWhatOMXMessage, mCodec);
     observer->setNotificationMessage(notify);
 
     mCodec->mComponentName = componentName;
@@ -4592,6 +4938,7 @@
 
     if (componentName.endsWith(".secure")) {
         mCodec->mFlags |= kFlagIsSecure;
+        mCodec->mFlags |= kFlagIsGrallocUsageProtected;
         mCodec->mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
     }
 
@@ -4630,6 +4977,7 @@
     mCodec->mRepeatFrameDelayUs = -1ll;
     mCodec->mInputFormat.clear();
     mCodec->mOutputFormat.clear();
+    mCodec->mBaseOutputFormat.clear();
 
     if (mCodec->mShutdownInProgress) {
         bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
@@ -4733,20 +5081,6 @@
         return false;
     }
 
-    sp<RefBase> obj;
-    if (msg->findObject("native-window", &obj)
-            && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
-        sp<NativeWindowWrapper> nativeWindow(
-                static_cast<NativeWindowWrapper *>(obj.get()));
-        CHECK(nativeWindow != NULL);
-        mCodec->mNativeWindow = nativeWindow->getNativeWindow();
-
-        native_window_set_scaling_mode(
-                mCodec->mNativeWindow.get(),
-                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
-    }
-    CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
-
     {
         sp<AMessage> notify = mCodec->mNotify->dup();
         notify->setInt32("what", CodecBase::kWhatComponentConfigured);
@@ -4802,6 +5136,21 @@
         }
     }
 
+    if (err == OK && mCodec->mMaxFps > 0) {
+        err = mCodec->mOMX->setInternalOption(
+                mCodec->mNode,
+                kPortIndexInput,
+                IOMX::INTERNAL_OPTION_MAX_FPS,
+                &mCodec->mMaxFps,
+                sizeof(mCodec->mMaxFps));
+
+        if (err != OK) {
+            ALOGE("[%s] Unable to configure max fps (err %d)",
+                    mCodec->mComponentName.c_str(),
+                    err);
+        }
+    }
+
     if (err == OK && mCodec->mTimePerCaptureUs > 0ll
             && mCodec->mTimePerFrameUs > 0ll) {
         int64_t timeLapse[2];
@@ -5356,6 +5705,7 @@
         case kWhatFlush:
         case kWhatShutdown:
         case kWhatResume:
+        case kWhatSetParameters:
         {
             if (msg->what() == kWhatResume) {
                 ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
@@ -5671,7 +6021,7 @@
 
         case OMX_EventPortSettingsChanged:
         {
-            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
+            sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec);
             msg->setInt32("type", omx_message::EVENT);
             msg->setInt32("node", mCodec->mNode);
             msg->setInt32("event", event);
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 9aa7d95..f53d7f0 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -31,19 +31,6 @@
 
 namespace android {
 
-AMRWriter::AMRWriter(const char *filename)
-    : mFd(-1),
-      mInitCheck(NO_INIT),
-      mStarted(false),
-      mPaused(false),
-      mResumed(false) {
-
-    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
-    if (mFd >= 0) {
-        mInitCheck = OK;
-    }
-}
-
 AMRWriter::AMRWriter(int fd)
     : mFd(dup(fd)),
       mInitCheck(mFd < 0? NO_INIT: OK),
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 7c4f92a..177293d 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -31,11 +31,13 @@
         MediaAdapter.cpp                  \
         MediaBuffer.cpp                   \
         MediaBufferGroup.cpp              \
+        MediaClock.cpp                    \
         MediaCodec.cpp                    \
         MediaCodecList.cpp                \
         MediaCodecSource.cpp              \
         MediaDefs.cpp                     \
         MediaExtractor.cpp                \
+        MidiExtractor.cpp                 \
         http/MediaHTTP.cpp                \
         MediaMuxer.cpp                    \
         MediaSource.cpp                   \
@@ -45,6 +47,7 @@
         OMXClient.cpp                     \
         OMXCodec.cpp                      \
         OggExtractor.cpp                  \
+        ProcessInfo.cpp                   \
         SampleIterator.cpp                \
         SampleTable.cpp                   \
         SkipCutBuffer.cpp                 \
@@ -68,11 +71,8 @@
         $(TOP)/frameworks/native/include/media/openmax \
         $(TOP)/external/flac/include \
         $(TOP)/external/tremolo \
-        $(TOP)/external/openssl/include \
         $(TOP)/external/libvpx/libwebm \
         $(TOP)/system/netd/include \
-        $(TOP)/external/icu/icu4c/source/common \
-        $(TOP)/external/icu/icu4c/source/i18n \
 
 LOCAL_SHARED_LIBRARIES := \
         libbinder \
@@ -112,13 +112,13 @@
         libstagefright_id3 \
         libFLAC \
         libmedia_helper \
-        libRScpp_static
 
 LOCAL_SHARED_LIBRARIES += \
         libstagefright_enc_common \
         libstagefright_avc_common \
         libstagefright_foundation \
-        libdl
+        libdl \
+        libRScpp \
 
 LOCAL_CFLAGS += -Wno-multichar
 
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 6a56729..87eef1e 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -878,11 +878,18 @@
         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)
-                && (mAudioSink == NULL || mAudioSink->realtime()))) {
-        // Don't AUTO_LOOP if we're being recorded, since that cannot be
-        // turned off and recording would go on indefinitely.
+            || (mFlags & AUTO_LOOPING)) {
 
         seekTo_l(0);
 
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index c3a940a..ad12bdd 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -219,7 +219,7 @@
         mCameraFlags |= FLAGS_HOT_CAMERA;
         mDeathNotifier = new DeathNotifier();
         // isBinderAlive needs linkToDeath to work.
-        mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
+        IInterface::asBinder(mCameraRecordingProxy)->linkToDeath(mDeathNotifier);
     }
 
     mCamera->lock();
@@ -702,7 +702,7 @@
     {
         Mutex::Autolock autoLock(mLock);
         if (mCameraRecordingProxy != 0) {
-            mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
+            IInterface::asBinder(mCameraRecordingProxy)->unlinkToDeath(mDeathNotifier);
             mCameraRecordingProxy.clear();
         }
         mCameraFlags = 0;
@@ -825,7 +825,7 @@
                 mFrameAvailableCondition.waitRelative(mLock,
                     mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
                 if (mCameraRecordingProxy != 0 &&
-                    !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
+                    !IInterface::asBinder(mCameraRecordingProxy)->isBinderAlive()) {
                     ALOGW("camera recording proxy is gone");
                     return ERROR_END_OF_STREAM;
                 }
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index c99db84..f7dcf35 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -22,6 +22,7 @@
 #include "include/DRMExtractor.h"
 #include "include/FLACExtractor.h"
 #include "include/HTTPBase.h"
+#include "include/MidiExtractor.h"
 #include "include/MP3Extractor.h"
 #include "include/MPEG2PSExtractor.h"
 #include "include/MPEG2TSExtractor.h"
@@ -172,6 +173,7 @@
     RegisterSniffer_l(SniffAAC);
     RegisterSniffer_l(SniffMPEG2PS);
     RegisterSniffer_l(SniffWVM);
+    RegisterSniffer_l(SniffMidi);
 
     char value[PROPERTY_VALUE_MAX];
     if (property_get("drm.service.enabled", value, NULL)
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index a7ca3da..f0db76b 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "FileSource"
+#include <utils/Log.h>
+
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/FileSource.h>
 #include <sys/types.h>
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
index 32291c8..77a652a 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libstagefright/HTTPBase.cpp
@@ -36,7 +36,8 @@
       mTotalTransferBytes(0),
       mPrevBandwidthMeasureTimeUs(0),
       mPrevEstimatedBandWidthKbps(0),
-      mBandWidthCollectFreqMs(5000) {
+      mBandWidthCollectFreqMs(5000),
+      mMaxBandwidthHistoryItems(100) {
 }
 
 void HTTPBase::addBandwidthMeasurement(
@@ -50,7 +51,7 @@
     mTotalTransferBytes += numBytes;
 
     mBandwidthHistory.push_back(entry);
-    if (++mNumBandwidthHistoryItems > 100) {
+    if (++mNumBandwidthHistoryItems > mMaxBandwidthHistoryItems) {
         BandwidthEntry *entry = &*mBandwidthHistory.begin();
         mTotalTransferTimeUs -= entry->mDelayUs;
         mTotalTransferBytes -= entry->mNumBytes;
@@ -74,7 +75,11 @@
 bool HTTPBase::estimateBandwidth(int32_t *bandwidth_bps) {
     Mutex::Autolock autoLock(mLock);
 
-    if (mNumBandwidthHistoryItems < 2) {
+    // Do not do bandwidth estimation if we don't have enough samples, or
+    // total bytes download are too small (<64K).
+    // Bandwidth estimation from these samples can often shoot up and cause
+    // unwanted bw adaption behaviors.
+    if (mNumBandwidthHistoryItems < 2 || mTotalTransferBytes < 65536) {
         return false;
     }
 
@@ -104,6 +109,10 @@
     return OK;
 }
 
+void HTTPBase::setBandwidthHistorySize(size_t numHistoryItems) {
+    mMaxBandwidthHistoryItems = numHistoryItems;
+}
+
 // static
 void HTTPBase::RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag) {
     int res = qtaguid_tagSocket(sockfd, kTag, uid);
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 9856f92..ef07aa0 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -135,7 +135,7 @@
 
     mNotify = notify;
 
-    (new AMessage(kWhatStart, id()))->post();
+    (new AMessage(kWhatStart, this))->post();
 }
 
 void MPEG2TSWriter::SourceInfo::stop() {
@@ -361,7 +361,7 @@
 }
 
 void MPEG2TSWriter::SourceInfo::readMore() {
-    (new AMessage(kWhatRead, id()))->post();
+    (new AMessage(kWhatRead, this))->post();
 }
 
 void MPEG2TSWriter::SourceInfo::onMessageReceived(const sp<AMessage> &msg) {
@@ -480,19 +480,6 @@
     init();
 }
 
-MPEG2TSWriter::MPEG2TSWriter(const char *filename)
-    : mFile(fopen(filename, "wb")),
-      mWriteCookie(NULL),
-      mWriteFunc(NULL),
-      mStarted(false),
-      mNumSourcesDone(0),
-      mNumTSPacketsWritten(0),
-      mNumTSPacketsBeforeMeta(0),
-      mPATContinuityCounter(0),
-      mPMTContinuityCounter(0) {
-    init();
-}
-
 MPEG2TSWriter::MPEG2TSWriter(
         void *cookie,
         ssize_t (*write)(void *cookie, const void *data, size_t size))
@@ -565,7 +552,7 @@
 
     for (size_t i = 0; i < mSources.size(); ++i) {
         sp<AMessage> notify =
-            new AMessage(kWhatSourceNotify, mReflector->id());
+            new AMessage(kWhatSourceNotify, mReflector);
 
         notify->setInt32("source-index", i);
 
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index d922dc0..d0f42cc 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -265,6 +265,8 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+static const bool kUseHexDump = false;
+
 static void hexdump(const void *_data, size_t size) {
     const uint8_t *data = (const uint8_t *)_data;
     size_t offset = 0;
@@ -352,6 +354,8 @@
 
 MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
     : mMoofOffset(0),
+      mMoofFound(false),
+      mMdatFound(false),
       mDataSource(source),
       mInitCheck(NO_INIT),
       mHasVideo(false),
@@ -488,7 +492,9 @@
 
     off64_t offset = 0;
     status_t err;
-    while (true) {
+    bool sawMoovOrSidx = false;
+
+    while (!(sawMoovOrSidx && (mMdatFound || mMoofFound))) {
         off64_t orig_offset = offset;
         err = parseChunk(&offset, 0);
 
@@ -500,23 +506,9 @@
             ALOGE("did not advance: 0x%lld->0x%lld", orig_offset, offset);
             err = ERROR_MALFORMED;
             break;
-        } else if (err == OK) {
-            continue;
+        } else if (err == UNKNOWN_ERROR) {
+            sawMoovOrSidx = true;
         }
-
-        uint32_t hdr[2];
-        if (mDataSource->readAt(offset, hdr, 8) < 8) {
-            break;
-        }
-        uint32_t chunk_type = ntohl(hdr[1]);
-        if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
-            // store the offset of the first segment
-            mMoofOffset = offset;
-        } else if (chunk_type != FOURCC('m', 'd', 'a', 't')) {
-            // keep parsing until we get to the data
-            continue;
-        }
-        break;
     }
 
     if (mInitCheck == OK) {
@@ -607,7 +599,6 @@
     if (size < 0) {
         return ERROR_IO;
     }
-    int32_t classSize = size;
     data_offset += numOfBytes;
 
     while(size >= 11 ) {
@@ -668,7 +659,6 @@
     if (size < 0) {
         return ERROR_IO;
     }
-    classSize = size;
     data_offset += numOfBytes;
 
     while (size > 0) {
@@ -766,7 +756,7 @@
         return ERROR_IO;
     }
     uint64_t chunk_size = ntohl(hdr[0]);
-    uint32_t chunk_type = ntohl(hdr[1]);
+    int32_t chunk_type = ntohl(hdr[1]);
     off64_t data_offset = *offset + 8;
 
     if (chunk_size == 1) {
@@ -806,23 +796,23 @@
     MakeFourCCString(chunk_type, chunk);
     ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
 
-#if 0
-    static const char kWhitespace[] = "                                        ";
-    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
-    printf("%sfound chunk '%s' of size %" PRIu64 "\n", indent, chunk, chunk_size);
+    if (kUseHexDump) {
+        static const char kWhitespace[] = "                                        ";
+        const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
+        printf("%sfound chunk '%s' of size %" PRIu64 "\n", indent, chunk, chunk_size);
 
-    char buffer[256];
-    size_t n = chunk_size;
-    if (n > sizeof(buffer)) {
-        n = sizeof(buffer);
-    }
-    if (mDataSource->readAt(*offset, buffer, n)
-            < (ssize_t)n) {
-        return ERROR_IO;
-    }
+        char buffer[256];
+        size_t n = chunk_size;
+        if (n > sizeof(buffer)) {
+            n = sizeof(buffer);
+        }
+        if (mDataSource->readAt(*offset, buffer, n)
+                < (ssize_t)n) {
+            return ERROR_IO;
+        }
 
-    hexdump(buffer, n);
-#endif
+        hexdump(buffer, n);
+    }
 
     PathAdder autoAdder(&mPath, chunk_type);
 
@@ -864,6 +854,12 @@
         case FOURCC('s', 'c', 'h', 'i'):
         case FOURCC('e', 'd', 't', 's'):
         {
+            if (chunk_type == FOURCC('m', 'o', 'o', 'f') && !mMoofFound) {
+                // store the offset of the first segment
+                mMoofFound = true;
+                mMoofOffset = *offset;
+            }
+
             if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
                 ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size);
 
@@ -999,6 +995,9 @@
 
                 int64_t duration;
                 int32_t samplerate;
+                if (!mLastTrack) {
+                    return ERROR_MALFORMED;
+                }
                 if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
                         mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
 
@@ -1141,7 +1140,7 @@
         {
             *offset += chunk_size;
 
-            if (chunk_data_size < 4) {
+            if (chunk_data_size < 4 || mLastTrack == NULL) {
                 return ERROR_MALFORMED;
             }
 
@@ -1298,7 +1297,7 @@
                 return ERROR_IO;
             }
 
-            uint16_t data_ref_index = U16_AT(&buffer[6]);
+            uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
             uint32_t num_channels = U16_AT(&buffer[16]);
 
             uint16_t sample_size = U16_AT(&buffer[18]);
@@ -1351,7 +1350,7 @@
                 return ERROR_IO;
             }
 
-            uint16_t data_ref_index = U16_AT(&buffer[6]);
+            uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
             uint16_t width = U16_AT(&buffer[6 + 18]);
             uint16_t height = U16_AT(&buffer[6 + 20]);
 
@@ -1533,13 +1532,13 @@
             break;
         }
 
-        // @xyz
-        case FOURCC('\xA9', 'x', 'y', 'z'):
+        // ©xyz
+        case FOURCC(0xA9, 'x', 'y', 'z'):
         {
             *offset += chunk_size;
 
-            // Best case the total data length inside "@xyz" box
-            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
+            // Best case the total data length inside "©xyz" box
+            // would be 8, for instance "©xyz" + "\x00\x04\x15\xc7" + "0+0/",
             // where "\x00\x04" is the text string length with value = 4,
             // "\0x15\xc7" is the language code = en, and "0+0" is a
             // location (string) value with longitude = 0 and latitude = 0.
@@ -1827,6 +1826,9 @@
         case FOURCC('m', 'd', 'a', 't'):
         {
             ALOGV("mdat chunk, drm: %d", mIsDrm);
+
+            mMdatFound = true;
+
             if (!mIsDrm) {
                 *offset += chunk_size;
                 break;
@@ -1867,7 +1869,6 @@
             if (chunk_data_size < 24) {
                 return ERROR_IO;
             }
-            uint32_t duration;
             Trex trex;
             if (!mDataSource->getUInt32(data_offset + 4, &trex.track_ID) ||
                 !mDataSource->getUInt32(data_offset + 8, &trex.default_sample_description_index) ||
@@ -2139,7 +2140,7 @@
         return ERROR_IO;
     }
 
-    uint64_t ctime, mtime, duration;
+    uint64_t ctime __unused, mtime __unused, duration __unused;
     int32_t id;
 
     if (version == 1) {
@@ -2161,12 +2162,13 @@
     size_t matrixOffset = dynSize + 16;
     int32_t a00 = U32_AT(&buffer[matrixOffset]);
     int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
-    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
     int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
     int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
-    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
 
 #if 0
+    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
+    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
+
     ALOGI("x' = %.2f * x + %.2f * y + %.2f",
          a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
     ALOGI("y' = %.2f * x + %.2f * y + %.2f",
@@ -2227,7 +2229,7 @@
     char chunk[5];
     MakeFourCCString(mPath[4], chunk);
     ALOGV("meta: %s @ %lld", chunk, offset);
-    switch (mPath[4]) {
+    switch ((int32_t)mPath[4]) {
         case FOURCC(0xa9, 'a', 'l', 'b'):
         {
             metadataKey = kKeyAlbum;
@@ -2718,10 +2720,10 @@
         return ERROR_MALFORMED;
     }
 
-#if 0
-    printf("ESD of size %d\n", csd_size);
-    hexdump(csd, csd_size);
-#endif
+    if (kUseHexDump) {
+        printf("ESD of size %d\n", csd_size);
+        hexdump(csd, csd_size);
+    }
 
     if (csd_size == 0) {
         // There's no further information, i.e. no codec specific data
@@ -2772,7 +2774,7 @@
 
     if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
         uint32_t extFreqIndex = br.getBits(4);
-        int32_t extSampleRate;
+        int32_t extSampleRate __unused;
         if (extFreqIndex == 15) {
             if (csd_size < 8) {
                 return ERROR_MALFORMED;
@@ -2822,12 +2824,12 @@
         if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
                 objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
                 objectType == AOT_ER_BSAC) {
-            const int32_t frameLengthFlag = br.getBits(1);
+            const int32_t frameLengthFlag __unused = br.getBits(1);
 
             const int32_t dependsOnCoreCoder = br.getBits(1);
 
             if (dependsOnCoreCoder ) {
-                const int32_t coreCoderDelay = br.getBits(14);
+                const int32_t coreCoderDelay __unused = br.getBits(14);
             }
 
             int32_t extensionFlag = -1;
@@ -2856,54 +2858,54 @@
             if (numChannels == 0) {
                 int32_t channelsEffectiveNum = 0;
                 int32_t channelsNum = 0;
-                const int32_t ElementInstanceTag = br.getBits(4);
-                const int32_t Profile = br.getBits(2);
-                const int32_t SamplingFrequencyIndex = br.getBits(4);
+                const int32_t ElementInstanceTag __unused = br.getBits(4);
+                const int32_t Profile __unused = br.getBits(2);
+                const int32_t SamplingFrequencyIndex __unused = br.getBits(4);
                 const int32_t NumFrontChannelElements = br.getBits(4);
                 const int32_t NumSideChannelElements = br.getBits(4);
                 const int32_t NumBackChannelElements = br.getBits(4);
                 const int32_t NumLfeChannelElements = br.getBits(2);
-                const int32_t NumAssocDataElements = br.getBits(3);
-                const int32_t NumValidCcElements = br.getBits(4);
+                const int32_t NumAssocDataElements __unused = br.getBits(3);
+                const int32_t NumValidCcElements __unused = br.getBits(4);
 
                 const int32_t MonoMixdownPresent = br.getBits(1);
                 if (MonoMixdownPresent != 0) {
-                    const int32_t MonoMixdownElementNumber = br.getBits(4);
+                    const int32_t MonoMixdownElementNumber __unused = br.getBits(4);
                 }
 
                 const int32_t StereoMixdownPresent = br.getBits(1);
                 if (StereoMixdownPresent != 0) {
-                    const int32_t StereoMixdownElementNumber = br.getBits(4);
+                    const int32_t StereoMixdownElementNumber __unused = br.getBits(4);
                 }
 
                 const int32_t MatrixMixdownIndexPresent = br.getBits(1);
                 if (MatrixMixdownIndexPresent != 0) {
-                    const int32_t MatrixMixdownIndex = br.getBits(2);
-                    const int32_t PseudoSurroundEnable = br.getBits(1);
+                    const int32_t MatrixMixdownIndex __unused = br.getBits(2);
+                    const int32_t PseudoSurroundEnable __unused = br.getBits(1);
                 }
 
                 int i;
                 for (i=0; i < NumFrontChannelElements; i++) {
                     const int32_t FrontElementIsCpe = br.getBits(1);
-                    const int32_t FrontElementTagSelect = br.getBits(4);
+                    const int32_t FrontElementTagSelect __unused = br.getBits(4);
                     channelsNum += FrontElementIsCpe ? 2 : 1;
                 }
 
                 for (i=0; i < NumSideChannelElements; i++) {
                     const int32_t SideElementIsCpe = br.getBits(1);
-                    const int32_t SideElementTagSelect = br.getBits(4);
+                    const int32_t SideElementTagSelect __unused = br.getBits(4);
                     channelsNum += SideElementIsCpe ? 2 : 1;
                 }
 
                 for (i=0; i < NumBackChannelElements; i++) {
                     const int32_t BackElementIsCpe = br.getBits(1);
-                    const int32_t BackElementTagSelect = br.getBits(4);
+                    const int32_t BackElementTagSelect __unused = br.getBits(4);
                     channelsNum += BackElementIsCpe ? 2 : 1;
                 }
                 channelsEffectiveNum = channelsNum;
 
                 for (i=0; i < NumLfeChannelElements; i++) {
-                    const int32_t LfeElementTagSelect = br.getBits(4);
+                    const int32_t LfeElementTagSelect __unused = br.getBits(4);
                     channelsNum += 1;
                 }
                 ALOGV("mpeg4 audio channelsNum = %d", channelsNum);
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 9f20b1d..6f6e362 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -29,6 +29,7 @@
 #include <utils/Log.h>
 
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MPEG4Writer.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MetaData.h>
@@ -62,6 +63,14 @@
 static const uint8_t kNalUnitTypePicParamSet = 0x08;
 static const int64_t kInitialDelayTimeUs     = 700000LL;
 
+static const char kMetaKey_Model[]      = "com.android.model";
+static const char kMetaKey_Version[]    = "com.android.version";
+static const char kMetaKey_Build[]      = "com.android.build";
+static const char kMetaKey_CaptureFps[] = "com.android.capture.fps";
+
+/* uncomment to include model and build in meta */
+//#define SHOW_MODEL_BUILD 1
+
 class MPEG4Writer::Track {
 public:
     Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
@@ -345,31 +354,6 @@
     Track &operator=(const Track &);
 };
 
-MPEG4Writer::MPEG4Writer(const char *filename)
-    : mFd(-1),
-      mInitCheck(NO_INIT),
-      mIsRealTimeRecording(true),
-      mUse4ByteNalLength(true),
-      mUse32BitOffset(true),
-      mIsFileSizeLimitExplicitlyRequested(false),
-      mPaused(false),
-      mStarted(false),
-      mWriterThreadStarted(false),
-      mOffset(0),
-      mMdatOffset(0),
-      mEstimatedMoovBoxSize(0),
-      mInterleaveDurationUs(1000000),
-      mLatitudex10000(0),
-      mLongitudex10000(0),
-      mAreGeoTagsAvailable(false),
-      mStartTimeOffsetMs(-1) {
-
-    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
-    if (mFd >= 0) {
-        mInitCheck = OK;
-    }
-}
-
 MPEG4Writer::MPEG4Writer(int fd)
     : mFd(dup(fd)),
       mInitCheck(mFd < 0? NO_INIT: OK),
@@ -383,11 +367,14 @@
       mOffset(0),
       mMdatOffset(0),
       mEstimatedMoovBoxSize(0),
+      mMoovExtraSize(0),
       mInterleaveDurationUs(1000000),
       mLatitudex10000(0),
       mLongitudex10000(0),
       mAreGeoTagsAvailable(false),
+      mMetaKeys(new AMessage()),
       mStartTimeOffsetMs(-1) {
+    addDeviceMeta();
 }
 
 MPEG4Writer::~MPEG4Writer() {
@@ -507,6 +494,34 @@
     return OK;
 }
 
+void MPEG4Writer::addDeviceMeta() {
+    // add device info and estimate space in 'moov'
+    char val[PROPERTY_VALUE_MAX];
+    size_t n;
+    // meta size is estimated by adding up the following:
+    // - meta header structures, which occur only once (total 66 bytes)
+    // - size for each key, which consists of a fixed header (32 bytes),
+    //   plus key length and data length.
+    mMoovExtraSize += 66;
+    if (property_get("ro.build.version.release", val, NULL)
+            && (n = strlen(val)) > 0) {
+        mMetaKeys->setString(kMetaKey_Version, val, n + 1);
+        mMoovExtraSize += sizeof(kMetaKey_Version) + n + 32;
+    }
+#ifdef SHOW_MODEL_BUILD
+    if (property_get("ro.product.model", val, NULL)
+            && (n = strlen(val)) > 0) {
+        mMetaKeys->setString(kMetaKey_Model, val, n + 1);
+        mMoovExtraSize += sizeof(kMetaKey_Model) + n + 32;
+    }
+    if (property_get("ro.build.display.id", val, NULL)
+            && (n = strlen(val)) > 0) {
+        mMetaKeys->setString(kMetaKey_Build, val, n + 1);
+        mMoovExtraSize += sizeof(kMetaKey_Build) + n + 32;
+    }
+#endif
+}
+
 int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
     // This implementation is highly experimental/heurisitic.
     //
@@ -560,6 +575,9 @@
         size = MAX_MOOV_BOX_SIZE;
     }
 
+    // Account for the extra stuff (Geo, meta keys, etc.)
+    size += mMoovExtraSize;
+
     ALOGI("limits: %" PRId64 "/%" PRId64 " bytes/us, bit rate: %d bps and the"
          " estimated moov size %" PRId64 " bytes",
          mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
@@ -971,6 +989,7 @@
     if (mAreGeoTagsAvailable) {
         writeUdtaBox();
     }
+    writeMetaBox();
     int32_t id = 1;
     for (List<Track *>::iterator it = mTracks.begin();
         it != mTracks.end(); ++it, ++id) {
@@ -1140,6 +1159,14 @@
     return bytes;
 }
 
+void MPEG4Writer::beginBox(uint32_t id) {
+    mBoxes.push_back(mWriteMoovBoxToMemory?
+            mMoovBoxBufferOffset: mOffset);
+
+    writeInt32(0);
+    writeInt32(id);
+}
+
 void MPEG4Writer::beginBox(const char *fourcc) {
     CHECK_EQ(strlen(fourcc), 4);
 
@@ -1264,6 +1291,18 @@
     mLatitudex10000 = latitudex10000;
     mLongitudex10000 = longitudex10000;
     mAreGeoTagsAvailable = true;
+    mMoovExtraSize += 30;
+    return OK;
+}
+
+status_t MPEG4Writer::setCaptureRate(float captureFps) {
+    if (captureFps <= 0.0f) {
+        return BAD_VALUE;
+    }
+
+    mMetaKeys->setFloat(kMetaKey_CaptureFps, captureFps);
+    mMoovExtraSize += sizeof(kMetaKey_CaptureFps) + 4 + 32;
+
     return OK;
 }
 
@@ -3095,6 +3134,103 @@
     endBox();
 }
 
+void MPEG4Writer::writeHdlr() {
+    beginBox("hdlr");
+    writeInt32(0); // Version, Flags
+    writeInt32(0); // Predefined
+    writeFourcc("mdta");
+    writeInt32(0); // Reserved[0]
+    writeInt32(0); // Reserved[1]
+    writeInt32(0); // Reserved[2]
+    writeInt8(0);  // Name (empty)
+    endBox();
+}
+
+void MPEG4Writer::writeKeys() {
+    size_t count = mMetaKeys->countEntries();
+
+    beginBox("keys");
+    writeInt32(0);     // Version, Flags
+    writeInt32(count); // Entry_count
+    for (size_t i = 0; i < count; i++) {
+        AMessage::Type type;
+        const char *key = mMetaKeys->getEntryNameAt(i, &type);
+        size_t n = strlen(key);
+        writeInt32(n + 8);
+        writeFourcc("mdta");
+        write(key, n); // write without the \0
+    }
+    endBox();
+}
+
+void MPEG4Writer::writeIlst() {
+    size_t count = mMetaKeys->countEntries();
+
+    beginBox("ilst");
+    for (size_t i = 0; i < count; i++) {
+        beginBox(i + 1); // key id (1-based)
+        beginBox("data");
+        AMessage::Type type;
+        const char *key = mMetaKeys->getEntryNameAt(i, &type);
+        switch (type) {
+            case AMessage::kTypeString:
+            {
+                AString val;
+                CHECK(mMetaKeys->findString(key, &val));
+                writeInt32(1); // type = UTF8
+                writeInt32(0); // default country/language
+                write(val.c_str(), strlen(val.c_str())); // write without \0
+                break;
+            }
+
+            case AMessage::kTypeFloat:
+            {
+                float val;
+                CHECK(mMetaKeys->findFloat(key, &val));
+                writeInt32(23); // type = float32
+                writeInt32(0);  // default country/language
+                writeInt32(*reinterpret_cast<int32_t *>(&val));
+                break;
+            }
+
+            case AMessage::kTypeInt32:
+            {
+                int32_t val;
+                CHECK(mMetaKeys->findInt32(key, &val));
+                writeInt32(67); // type = signed int32
+                writeInt32(0);  // default country/language
+                writeInt32(val);
+                break;
+            }
+
+            default:
+            {
+                ALOGW("Unsupported key type, writing 0 instead");
+                writeInt32(77); // type = unsigned int32
+                writeInt32(0);  // default country/language
+                writeInt32(0);
+                break;
+            }
+        }
+        endBox(); // data
+        endBox(); // key id
+    }
+    endBox(); // ilst
+}
+
+void MPEG4Writer::writeMetaBox() {
+    size_t count = mMetaKeys->countEntries();
+    if (count == 0) {
+        return;
+    }
+
+    beginBox("meta");
+    writeHdlr();
+    writeKeys();
+    writeIlst();
+    endBox();
+}
+
 /*
  * Geodata is stored according to ISO-6709 standard.
  */
diff --git a/media/libstagefright/MediaClock.cpp b/media/libstagefright/MediaClock.cpp
new file mode 100644
index 0000000..38db5e4
--- /dev/null
+++ b/media/libstagefright/MediaClock.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "MediaClock"
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaClock.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+
+namespace android {
+
+MediaClock::MediaClock()
+    : mAnchorTimeMediaUs(-1),
+      mAnchorTimeRealUs(-1),
+      mMaxTimeMediaUs(INT64_MAX),
+      mStartingTimeMediaUs(-1),
+      mPlaybackRate(1.0) {
+}
+
+MediaClock::~MediaClock() {
+}
+
+void MediaClock::setStartingTimeMedia(int64_t startingTimeMediaUs) {
+    Mutex::Autolock autoLock(mLock);
+    mStartingTimeMediaUs = startingTimeMediaUs;
+}
+
+void MediaClock::clearAnchor() {
+    Mutex::Autolock autoLock(mLock);
+    mAnchorTimeMediaUs = -1;
+    mAnchorTimeRealUs = -1;
+}
+
+void MediaClock::updateAnchor(
+        int64_t anchorTimeMediaUs,
+        int64_t anchorTimeRealUs,
+        int64_t maxTimeMediaUs) {
+    if (anchorTimeMediaUs < 0 || anchorTimeRealUs < 0) {
+        ALOGW("reject anchor time since it is negative.");
+        return;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+    int64_t nowUs = ALooper::GetNowUs();
+    int64_t nowMediaUs =
+        anchorTimeMediaUs + (nowUs - anchorTimeRealUs) * (double)mPlaybackRate;
+    if (nowMediaUs < 0) {
+        ALOGW("reject anchor time since it leads to negative media time.");
+        return;
+    }
+    mAnchorTimeRealUs = nowUs;
+    mAnchorTimeMediaUs = nowMediaUs;
+    mMaxTimeMediaUs = maxTimeMediaUs;
+}
+
+void MediaClock::updateMaxTimeMedia(int64_t maxTimeMediaUs) {
+    Mutex::Autolock autoLock(mLock);
+    mMaxTimeMediaUs = maxTimeMediaUs;
+}
+
+void MediaClock::setPlaybackRate(float rate) {
+    CHECK_GE(rate, 0.0);
+    Mutex::Autolock autoLock(mLock);
+    if (mAnchorTimeRealUs == -1) {
+        mPlaybackRate = rate;
+        return;
+    }
+
+    int64_t nowUs = ALooper::GetNowUs();
+    mAnchorTimeMediaUs += (nowUs - mAnchorTimeRealUs) * (double)mPlaybackRate;
+    if (mAnchorTimeMediaUs < 0) {
+        ALOGW("setRate: anchor time should not be negative, set to 0.");
+        mAnchorTimeMediaUs = 0;
+    }
+    mAnchorTimeRealUs = nowUs;
+    mPlaybackRate = rate;
+}
+
+status_t MediaClock::getMediaTime(
+        int64_t realUs, int64_t *outMediaUs, bool allowPastMaxTime) {
+    Mutex::Autolock autoLock(mLock);
+    return getMediaTime_l(realUs, outMediaUs, allowPastMaxTime);
+}
+
+status_t MediaClock::getMediaTime_l(
+        int64_t realUs, int64_t *outMediaUs, bool allowPastMaxTime) {
+    if (mAnchorTimeRealUs == -1) {
+        return NO_INIT;
+    }
+
+    int64_t mediaUs = mAnchorTimeMediaUs
+            + (realUs - mAnchorTimeRealUs) * (double)mPlaybackRate;
+    if (mediaUs > mMaxTimeMediaUs && !allowPastMaxTime) {
+        mediaUs = mMaxTimeMediaUs;
+    }
+    if (mediaUs < mStartingTimeMediaUs) {
+        mediaUs = mStartingTimeMediaUs;
+    }
+    if (mediaUs < 0) {
+        mediaUs = 0;
+    }
+    *outMediaUs = mediaUs;
+    return OK;
+}
+
+status_t MediaClock::getRealTimeFor(int64_t targetMediaUs, int64_t *outRealUs) {
+    Mutex::Autolock autoLock(mLock);
+    if (mPlaybackRate == 0.0) {
+        return NO_INIT;
+    }
+
+    int64_t nowUs = ALooper::GetNowUs();
+    int64_t nowMediaUs;
+    status_t status =
+            getMediaTime_l(nowUs, &nowMediaUs, true /* allowPastMaxTime */);
+    if (status != OK) {
+        return status;
+    }
+    *outRealUs = (targetMediaUs - nowMediaUs) / (double)mPlaybackRate + nowUs;
+    return OK;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 673d375..0597f1d 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -174,7 +174,7 @@
 }
 
 // static
-void MediaCodec::PostReplyWithError(int32_t replyID, int32_t err) {
+void MediaCodec::PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err) {
     sp<AMessage> response = new AMessage;
     response->setInt32("err", err);
     response->postReply(replyID);
@@ -237,9 +237,9 @@
 
     mLooper->registerHandler(this);
 
-    mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));
+    mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, this));
 
-    sp<AMessage> msg = new AMessage(kWhatInit, id());
+    sp<AMessage> msg = new AMessage(kWhatInit, this);
     msg->setString("name", name);
     msg->setInt32("nameIsType", nameIsType);
 
@@ -252,7 +252,7 @@
 }
 
 status_t MediaCodec::setCallback(const sp<AMessage> &callback) {
-    sp<AMessage> msg = new AMessage(kWhatSetCallback, id());
+    sp<AMessage> msg = new AMessage(kWhatSetCallback, this);
     msg->setMessage("callback", callback);
 
     sp<AMessage> response;
@@ -264,7 +264,7 @@
         const sp<Surface> &nativeWindow,
         const sp<ICrypto> &crypto,
         uint32_t flags) {
-    sp<AMessage> msg = new AMessage(kWhatConfigure, id());
+    sp<AMessage> msg = new AMessage(kWhatConfigure, this);
 
     msg->setMessage("format", format);
     msg->setInt32("flags", flags);
@@ -298,7 +298,7 @@
 
 status_t MediaCodec::createInputSurface(
         sp<IGraphicBufferProducer>* bufferProducer) {
-    sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, id());
+    sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, this);
 
     sp<AMessage> response;
     status_t err = PostAndAwaitResponse(msg, &response);
@@ -317,21 +317,21 @@
 }
 
 status_t MediaCodec::start() {
-    sp<AMessage> msg = new AMessage(kWhatStart, id());
+    sp<AMessage> msg = new AMessage(kWhatStart, this);
 
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
 
 status_t MediaCodec::stop() {
-    sp<AMessage> msg = new AMessage(kWhatStop, id());
+    sp<AMessage> msg = new AMessage(kWhatStop, this);
 
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
 
 status_t MediaCodec::release() {
-    sp<AMessage> msg = new AMessage(kWhatRelease, id());
+    sp<AMessage> msg = new AMessage(kWhatRelease, this);
 
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
@@ -383,7 +383,7 @@
         errorDetailMsg->clear();
     }
 
-    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
+    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
     msg->setSize("index", index);
     msg->setSize("offset", offset);
     msg->setSize("size", size);
@@ -410,7 +410,7 @@
         errorDetailMsg->clear();
     }
 
-    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
+    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
     msg->setSize("index", index);
     msg->setSize("offset", offset);
     msg->setPointer("subSamples", (void *)subSamples);
@@ -429,7 +429,7 @@
 }
 
 status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
-    sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
+    sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, this);
     msg->setInt64("timeoutUs", timeoutUs);
 
     sp<AMessage> response;
@@ -450,7 +450,7 @@
         int64_t *presentationTimeUs,
         uint32_t *flags,
         int64_t timeoutUs) {
-    sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id());
+    sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, this);
     msg->setInt64("timeoutUs", timeoutUs);
 
     sp<AMessage> response;
@@ -469,7 +469,7 @@
 }
 
 status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
-    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
+    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
     msg->setSize("index", index);
     msg->setInt32("render", true);
 
@@ -478,7 +478,7 @@
 }
 
 status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
-    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
+    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
     msg->setSize("index", index);
     msg->setInt32("render", true);
     msg->setInt64("timestampNs", timestampNs);
@@ -488,7 +488,7 @@
 }
 
 status_t MediaCodec::releaseOutputBuffer(size_t index) {
-    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
+    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
     msg->setSize("index", index);
 
     sp<AMessage> response;
@@ -496,14 +496,14 @@
 }
 
 status_t MediaCodec::signalEndOfInputStream() {
-    sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, id());
+    sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, this);
 
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
 
 status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
-    sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id());
+    sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, this);
 
     sp<AMessage> response;
     status_t err;
@@ -517,7 +517,7 @@
 }
 
 status_t MediaCodec::getInputFormat(sp<AMessage> *format) const {
-    sp<AMessage> msg = new AMessage(kWhatGetInputFormat, id());
+    sp<AMessage> msg = new AMessage(kWhatGetInputFormat, this);
 
     sp<AMessage> response;
     status_t err;
@@ -531,7 +531,7 @@
 }
 
 status_t MediaCodec::getName(AString *name) const {
-    sp<AMessage> msg = new AMessage(kWhatGetName, id());
+    sp<AMessage> msg = new AMessage(kWhatGetName, this);
 
     sp<AMessage> response;
     status_t err;
@@ -545,7 +545,7 @@
 }
 
 status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
-    sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
+    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
     msg->setInt32("portIndex", kPortIndexInput);
     msg->setPointer("buffers", buffers);
 
@@ -554,7 +554,7 @@
 }
 
 status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
-    sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
+    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
     msg->setInt32("portIndex", kPortIndexOutput);
     msg->setPointer("buffers", buffers);
 
@@ -612,20 +612,20 @@
 }
 
 status_t MediaCodec::flush() {
-    sp<AMessage> msg = new AMessage(kWhatFlush, id());
+    sp<AMessage> msg = new AMessage(kWhatFlush, this);
 
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
 
 status_t MediaCodec::requestIDRFrame() {
-    (new AMessage(kWhatRequestIDRFrame, id()))->post();
+    (new AMessage(kWhatRequestIDRFrame, this))->post();
 
     return OK;
 }
 
 void MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
-    sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, id());
+    sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this);
     msg->setMessage("notify", notify);
     msg->post();
 }
@@ -650,7 +650,7 @@
     }
 }
 
-bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) {
+bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
     if (!isExecuting() || (mFlags & kFlagIsAsync)
             || (newRequest && (mFlags & kFlagDequeueInputPending))) {
         PostReplyWithError(replyID, INVALID_OPERATION);
@@ -674,7 +674,7 @@
     return true;
 }
 
-bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) {
+bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
     sp<AMessage> response = new AMessage;
 
     if (!isExecuting() || (mFlags & kFlagIsAsync)
@@ -879,9 +879,9 @@
                     CHECK(msg->findString("componentName", &mComponentName));
 
                     if (mComponentName.startsWith("OMX.google.")) {
-                        mFlags |= kFlagIsSoftwareCodec;
+                        mFlags |= kFlagUsesSoftwareRenderer;
                     } else {
-                        mFlags &= ~kFlagIsSoftwareCodec;
+                        mFlags &= ~kFlagUsesSoftwareRenderer;
                     }
 
                     if (mComponentName.endsWith(".secure")) {
@@ -904,6 +904,11 @@
                     CHECK(msg->findMessage("input-format", &mInputFormat));
                     CHECK(msg->findMessage("output-format", &mOutputFormat));
 
+                    int32_t usingSwRenderer;
+                    if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
+                            && usingSwRenderer) {
+                        mFlags |= kFlagUsesSoftwareRenderer;
+                    }
                     setState(CONFIGURED);
                     (new AMessage)->postReply(mReplyID);
                     break;
@@ -999,7 +1004,7 @@
 
                     if (mSoftRenderer == NULL &&
                             mNativeWindow != NULL &&
-                            (mFlags & kFlagIsSoftwareCodec)) {
+                            (mFlags & kFlagUsesSoftwareRenderer)) {
                         AString mime;
                         CHECK(msg->findString("mime", &mime));
 
@@ -1024,11 +1029,13 @@
 
                     // Notify mCrypto of video resolution changes
                     if (mCrypto != NULL) {
-                      int32_t height, width;
-                      if (mOutputFormat->findInt32("height", &height) &&
-                          mOutputFormat->findInt32("width", &width)) {
-                        mCrypto->notifyResolution(width, height);
-                      }
+                        int32_t left, top, right, bottom, width, height;
+                        if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
+                            mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
+                        } else if (mOutputFormat->findInt32("width", &width)
+                                && mOutputFormat->findInt32("height", &height)) {
+                            mCrypto->notifyResolution(width, height);
+                        }
                     }
 
                     break;
@@ -1191,7 +1198,7 @@
 
         case kWhatInit:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (mState != UNINITIALIZED) {
@@ -1227,7 +1234,7 @@
 
         case kWhatSetCallback:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (mState == UNINITIALIZED
@@ -1259,7 +1266,7 @@
 
         case kWhatConfigure:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (mState != INITIALIZED) {
@@ -1316,7 +1323,7 @@
 
         case kWhatCreateInputSurface:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             // Must be configured, but can't have been started yet.
@@ -1332,12 +1339,14 @@
 
         case kWhatStart:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (mState == FLUSHED) {
+                setState(STARTED);
                 mCodec->signalResume();
                 PostReplyWithError(replyID, OK);
+                break;
             } else if (mState != CONFIGURED) {
                 PostReplyWithError(replyID, INVALID_OPERATION);
                 break;
@@ -1356,12 +1365,15 @@
             State targetState =
                 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
-            if (!(mFlags & kFlagIsComponentAllocated) && mState != INITIALIZED
+            if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1
+                    && mState != INITIALIZED
                     && mState != CONFIGURED && !isExecuting()) {
-                // We may be in "UNINITIALIZED" state already and
+                // 1) Permit release to shut down the component if allocated.
+                //
+                // 2) We may be in "UNINITIALIZED" state already and
                 // also shutdown the encoder/decoder without the
                 // client being aware of this if media server died while
                 // we were being stopped. The client would assume that
@@ -1401,7 +1413,7 @@
 
         case kWhatDequeueInputBuffer:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (mFlags & kFlagIsAsync) {
@@ -1433,7 +1445,7 @@
 
             if (timeoutUs > 0ll) {
                 sp<AMessage> timeoutMsg =
-                    new AMessage(kWhatDequeueInputTimedOut, id());
+                    new AMessage(kWhatDequeueInputTimedOut, this);
                 timeoutMsg->setInt32(
                         "generation", ++mDequeueInputTimeoutGeneration);
                 timeoutMsg->post(timeoutUs);
@@ -1462,7 +1474,7 @@
 
         case kWhatQueueInputBuffer:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (!isExecuting()) {
@@ -1481,7 +1493,7 @@
 
         case kWhatDequeueOutputBuffer:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (mFlags & kFlagIsAsync) {
@@ -1507,7 +1519,7 @@
 
             if (timeoutUs > 0ll) {
                 sp<AMessage> timeoutMsg =
-                    new AMessage(kWhatDequeueOutputTimedOut, id());
+                    new AMessage(kWhatDequeueOutputTimedOut, this);
                 timeoutMsg->setInt32(
                         "generation", ++mDequeueOutputTimeoutGeneration);
                 timeoutMsg->post(timeoutUs);
@@ -1536,7 +1548,7 @@
 
         case kWhatReleaseOutputBuffer:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (!isExecuting()) {
@@ -1555,7 +1567,7 @@
 
         case kWhatSignalEndOfInputStream:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (!isExecuting()) {
@@ -1573,7 +1585,7 @@
 
         case kWhatGetBuffers:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (!isExecuting() || (mFlags & kFlagIsAsync)) {
@@ -1607,7 +1619,7 @@
 
         case kWhatFlush:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (!isExecuting()) {
@@ -1633,7 +1645,7 @@
             sp<AMessage> format =
                 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if ((mState != CONFIGURED && mState != STARTING &&
@@ -1670,7 +1682,7 @@
 
         case kWhatGetName:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             if (mComponentName.empty()) {
@@ -1686,7 +1698,7 @@
 
         case kWhatSetParameters:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             sp<AMessage> params;
@@ -1709,7 +1721,7 @@
     size_t i = 0;
     for (;;) {
         sp<ABuffer> csd;
-        if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) {
+        if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
             break;
         }
 
@@ -1740,7 +1752,7 @@
 
     AString errorDetailMsg;
 
-    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
+    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
     msg->setSize("index", bufferIndex);
     msg->setSize("offset", 0);
     msg->setSize("size", csd->size());
@@ -2195,7 +2207,7 @@
 }
 
 status_t MediaCodec::setParameters(const sp<AMessage> &params) {
-    sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
+    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
     msg->setMessage("params", params);
 
     sp<AMessage> response;
@@ -2232,7 +2244,7 @@
             memcpy(csd->data() + 4, nalStart, nalSize);
 
             mOutputFormat->setBuffer(
-                    StringPrintf("csd-%u", csdIndex).c_str(), csd);
+                    AStringPrintf("csd-%u", csdIndex).c_str(), csd);
 
             ++csdIndex;
         }
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 5b8be46..cf6e937 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -62,6 +62,14 @@
 
 sp<IMediaCodecList> MediaCodecList::sRemoteList;
 
+sp<MediaCodecList::BinderDeathObserver> MediaCodecList::sBinderDeathObserver;
+
+void MediaCodecList::BinderDeathObserver::binderDied(const wp<IBinder> &who __unused) {
+    Mutex::Autolock _l(sRemoteInitMutex);
+    sRemoteList.clear();
+    sBinderDeathObserver.clear();
+}
+
 // static
 sp<IMediaCodecList> MediaCodecList::getInstance() {
     Mutex::Autolock _l(sRemoteInitMutex);
@@ -72,8 +80,11 @@
             interface_cast<IMediaPlayerService>(binder);
         if (service.get() != NULL) {
             sRemoteList = service->getCodecList();
+            if (sRemoteList != NULL) {
+                sBinderDeathObserver = new BinderDeathObserver();
+                binder->linkToDeath(sBinderDeathObserver.get());
+            }
         }
-
         if (sRemoteList == NULL) {
             // if failed to get remote list, create local list
             sRemoteList = getLocalInstance();
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 0fecda8..b6fa810 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -121,7 +121,7 @@
     mLooper->registerHandler(this);
     mNotify = notify;
 
-    sp<AMessage> msg = new AMessage(kWhatStart, id());
+    sp<AMessage> msg = new AMessage(kWhatStart, this);
     msg->setObject("meta", meta);
     return postSynchronouslyAndReturnError(msg);
 }
@@ -137,19 +137,19 @@
     mSource->stop();
     ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video");
 
-    (new AMessage(kWhatStop, id()))->post();
+    (new AMessage(kWhatStop, this))->post();
 }
 
 void MediaCodecSource::Puller::pause() {
-    (new AMessage(kWhatPause, id()))->post();
+    (new AMessage(kWhatPause, this))->post();
 }
 
 void MediaCodecSource::Puller::resume() {
-    (new AMessage(kWhatResume, id()))->post();
+    (new AMessage(kWhatResume, this))->post();
 }
 
 void MediaCodecSource::Puller::schedulePull() {
-    sp<AMessage> msg = new AMessage(kWhatPull, id());
+    sp<AMessage> msg = new AMessage(kWhatPull, this);
     msg->setInt32("generation", mPullGeneration);
     msg->post();
 }
@@ -182,7 +182,7 @@
             sp<AMessage> response = new AMessage;
             response->setInt32("err", err);
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
             response->postReply(replyID);
             break;
@@ -269,13 +269,13 @@
 }
 
 status_t MediaCodecSource::start(MetaData* params) {
-    sp<AMessage> msg = new AMessage(kWhatStart, mReflector->id());
+    sp<AMessage> msg = new AMessage(kWhatStart, mReflector);
     msg->setObject("meta", params);
     return postSynchronouslyAndReturnError(msg);
 }
 
 status_t MediaCodecSource::stop() {
-    sp<AMessage> msg = new AMessage(kWhatStop, mReflector->id());
+    sp<AMessage> msg = new AMessage(kWhatStop, mReflector);
     status_t err = postSynchronouslyAndReturnError(msg);
 
     // mPuller->stop() needs to be done outside MediaCodecSource's looper,
@@ -294,7 +294,7 @@
 }
 
 status_t MediaCodecSource::pause() {
-    (new AMessage(kWhatPause, mReflector->id()))->post();
+    (new AMessage(kWhatPause, mReflector))->post();
     return OK;
 }
 
@@ -422,24 +422,15 @@
         }
     }
 
+    mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
+    mEncoder->setCallback(mEncoderActivityNotify);
+
     err = mEncoder->start();
 
     if (err != OK) {
         return err;
     }
 
-    err = mEncoder->getInputBuffers(&mEncoderInputBuffers);
-
-    if (err != OK) {
-        return err;
-    }
-
-    err = mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
-
-    if (err != OK) {
-        return err;
-    }
-
     mEncoderReachedEOS = false;
     mErrorCode = OK;
 
@@ -461,14 +452,6 @@
             mbuf->release();
         }
     }
-
-    for (size_t i = 0; i < mEncoderInputBuffers.size(); ++i) {
-        sp<ABuffer> accessUnit = mEncoderInputBuffers.itemAt(i);
-        accessUnit->setMediaBufferBase(NULL);
-    }
-
-    mEncoderInputBuffers.clear();
-    mEncoderOutputBuffers.clear();
 }
 
 status_t MediaCodecSource::postSynchronouslyAndReturnError(
@@ -508,7 +491,7 @@
     if (mStopping && mEncoderReachedEOS) {
         ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
         // posting reply to everyone that's waiting
-        List<uint32_t>::iterator it;
+        List<sp<AReplyToken>>::iterator it;
         for (it = mStopReplyIDQueue.begin();
                 it != mStopReplyIDQueue.end(); it++) {
             (new AMessage)->postReply(*it);
@@ -539,20 +522,6 @@
     }
 }
 
-void MediaCodecSource::scheduleDoMoreWork() {
-    if (mDoMoreWorkPending) {
-        return;
-    }
-
-    mDoMoreWorkPending = true;
-
-    if (mEncoderActivityNotify == NULL) {
-        mEncoderActivityNotify = new AMessage(
-                kWhatEncoderActivity, mReflector->id());
-    }
-    mEncoder->requestActivityNotification(mEncoderActivityNotify);
-}
-
 status_t MediaCodecSource::feedEncoderInputBuffers() {
     while (!mInputBufferQueue.empty()
             && !mAvailEncoderInputIndices.empty()) {
@@ -587,16 +556,22 @@
 #endif // DEBUG_DRIFT_TIME
             }
 
+            sp<ABuffer> inbuf;
+            status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
+            if (err != OK || inbuf == NULL) {
+                mbuf->release();
+                signalEOS();
+                break;
+            }
+
             size = mbuf->size();
 
-            memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(),
-                   mbuf->data(), size);
+            memcpy(inbuf->data(), mbuf->data(), size);
 
             if (mIsVideo) {
                 // video encoder will release MediaBuffer when done
                 // with underlying data.
-                mEncoderInputBuffers.itemAt(bufferIndex)->setMediaBufferBase(
-                        mbuf);
+                inbuf->setMediaBufferBase(mbuf);
             } else {
                 mbuf->release();
             }
@@ -615,50 +590,119 @@
     return OK;
 }
 
-status_t MediaCodecSource::doMoreWork(int32_t numInput, int32_t numOutput) {
+status_t MediaCodecSource::onStart(MetaData *params) {
+    if (mStopping) {
+        ALOGE("Failed to start while we're stopping");
+        return INVALID_OPERATION;
+    }
+
+    if (mStarted) {
+        ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
+        if (mFlags & FLAG_USE_SURFACE_INPUT) {
+            resume();
+        } else {
+            CHECK(mPuller != NULL);
+            mPuller->resume();
+        }
+        return OK;
+    }
+
+    ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
+
     status_t err = OK;
 
-    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
-        while (numInput-- > 0) {
-            size_t bufferIndex;
-            err = mEncoder->dequeueInputBuffer(&bufferIndex);
+    if (mFlags & FLAG_USE_SURFACE_INPUT) {
+        int64_t startTimeUs;
+        if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
+            startTimeUs = -1ll;
+        }
+        resume(startTimeUs);
+    } else {
+        CHECK(mPuller != NULL);
+        sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector);
+        err = mPuller->start(params, notify);
+        if (err != OK) {
+            return err;
+        }
+    }
 
-            if (err != OK) {
+    ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
+
+    mStarted = true;
+    return OK;
+}
+
+void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
+    switch (msg->what()) {
+    case kWhatPullerNotify:
+    {
+        MediaBuffer *mbuf;
+        CHECK(msg->findPointer("accessUnit", (void**)&mbuf));
+
+        if (mbuf == NULL) {
+            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);
+
+        feedEncoderInputBuffers();
+
+        break;
+    }
+    case kWhatEncoderActivity:
+    {
+        if (mEncoder == NULL) {
+            break;
+        }
+
+        int32_t cbID;
+        CHECK(msg->findInt32("callbackID", &cbID));
+        if (cbID == MediaCodec::CB_INPUT_AVAILABLE) {
+            int32_t index;
+            CHECK(msg->findInt32("index", &index));
+
+            mAvailEncoderInputIndices.push_back(index);
+            feedEncoderInputBuffers();
+        } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
+            int32_t index;
+            size_t offset;
+            size_t size;
+            int64_t timeUs;
+            int32_t flags;
+            native_handle_t* handle = NULL;
+
+            CHECK(msg->findInt32("index", &index));
+            CHECK(msg->findSize("offset", &offset));
+            CHECK(msg->findSize("size", &size));
+            CHECK(msg->findInt64("timeUs", &timeUs));
+            CHECK(msg->findInt32("flags", &flags));
+
+            if (flags & MediaCodec::BUFFER_FLAG_EOS) {
+                mEncoder->releaseOutputBuffer(index);
+                signalEOS();
                 break;
             }
 
-            mAvailEncoderInputIndices.push_back(bufferIndex);
-        }
-
-        feedEncoderInputBuffers();
-    }
-
-    while (numOutput-- > 0) {
-        size_t bufferIndex;
-        size_t offset;
-        size_t size;
-        int64_t timeUs;
-        uint32_t flags;
-        native_handle_t* handle = NULL;
-        err = mEncoder->dequeueOutputBuffer(
-                &bufferIndex, &offset, &size, &timeUs, &flags);
-
-        if (err != OK) {
-            if (err == INFO_FORMAT_CHANGED) {
-                continue;
-            } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
-                mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
-                continue;
+            sp<ABuffer> outbuf;
+            status_t err = mEncoder->getOutputBuffer(index, &outbuf);
+            if (err != OK || outbuf == NULL) {
+                signalEOS();
+                break;
             }
 
-            if (err == -EAGAIN) {
-                err = OK;
-            }
-            break;
-        }
-        if (!(flags & MediaCodec::BUFFER_FLAG_EOS)) {
-            sp<ABuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex);
-
             MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
             memcpy(mbuf->data(), outbuf->data(), outbuf->size());
 
@@ -709,125 +753,20 @@
                 mOutputBufferQueue.push_back(mbuf);
                 mOutputBufferCond.signal();
             }
-        }
 
-        mEncoder->releaseOutputBuffer(bufferIndex);
-
-        if (flags & MediaCodec::BUFFER_FLAG_EOS) {
-            err = ERROR_END_OF_STREAM;
-            break;
-        }
-    }
-
-    return err;
-}
-
-status_t MediaCodecSource::onStart(MetaData *params) {
-    if (mStopping) {
-        ALOGE("Failed to start while we're stopping");
-        return INVALID_OPERATION;
-    }
-
-    if (mStarted) {
-        ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
-        if (mFlags & FLAG_USE_SURFACE_INPUT) {
-            resume();
-        } else {
-            CHECK(mPuller != NULL);
-            mPuller->resume();
-        }
-        return OK;
-    }
-
-    ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
-
-    status_t err = OK;
-
-    if (mFlags & FLAG_USE_SURFACE_INPUT) {
-        int64_t startTimeUs;
-        if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
-            startTimeUs = -1ll;
-        }
-        resume(startTimeUs);
-        scheduleDoMoreWork();
-    } else {
-        CHECK(mPuller != NULL);
-        sp<AMessage> notify = new AMessage(
-                kWhatPullerNotify, mReflector->id());
-        err = mPuller->start(params, notify);
-        if (err != OK) {
-            return err;
-        }
-    }
-
-    ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
-
-    mStarted = true;
-    return OK;
-}
-
-void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
-    switch (msg->what()) {
-    case kWhatPullerNotify:
-    {
-        MediaBuffer *mbuf;
-        CHECK(msg->findPointer("accessUnit", (void**)&mbuf));
-
-        if (mbuf == NULL) {
-            ALOGV("puller (%s) reached EOS",
-                    mIsVideo ? "video" : "audio");
+            mEncoder->releaseOutputBuffer(index);
+       } else if (cbID == MediaCodec::CB_ERROR) {
+            status_t err;
+            CHECK(msg->findInt32("err", &err));
+            ALOGE("Encoder (%s) reported error : 0x%x",
+                    mIsVideo ? "video" : "audio", err);
             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);
-
-        feedEncoderInputBuffers();
-        scheduleDoMoreWork();
-
-        break;
-    }
-    case kWhatEncoderActivity:
-    {
-        mDoMoreWorkPending = false;
-
-        if (mEncoder == NULL) {
-            break;
-        }
-
-        int32_t numInput, numOutput;
-
-        if (!msg->findInt32("input-buffers", &numInput)) {
-            numInput = INT32_MAX;
-        }
-        if (!msg->findInt32("output-buffers", &numOutput)) {
-            numOutput = INT32_MAX;
-        }
-
-        status_t err = doMoreWork(numInput, numOutput);
-
-        if (err == OK) {
-            scheduleDoMoreWork();
-        } else {
-            // reached EOS, or error
-            signalEOS(err);
-        }
-
-        break;
+       }
+       break;
     }
     case kWhatStart:
     {
-        uint32_t replyID;
+        sp<AReplyToken> replyID;
         CHECK(msg->senderAwaitsResponse(&replyID));
 
         sp<RefBase> obj;
@@ -843,7 +782,7 @@
     {
         ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio");
 
-        uint32_t replyID;
+        sp<AReplyToken> replyID;
         CHECK(msg->senderAwaitsResponse(&replyID));
 
         if (mEncoderReachedEOS) {
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index d48dd84..c48a5ae 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -34,6 +34,7 @@
 const char *MEDIA_MIMETYPE_AUDIO_MPEG = "audio/mpeg";
 const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I = "audio/mpeg-L1";
 const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II = "audio/mpeg-L2";
+const char *MEDIA_MIMETYPE_AUDIO_MIDI = "audio/midi";
 const char *MEDIA_MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
 const char *MEDIA_MIMETYPE_AUDIO_QCELP = "audio/qcelp";
 const char *MEDIA_MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
@@ -45,6 +46,7 @@
 const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS = "audio/aac-adts";
 const char *MEDIA_MIMETYPE_AUDIO_MSGSM = "audio/gsm";
 const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3";
+const char *MEDIA_MIMETYPE_AUDIO_EAC3 = "audio/eac3";
 
 const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";
 const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav";
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 9ab6611..e21fe6e 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -29,6 +29,7 @@
 #include "include/WVMExtractor.h"
 #include "include/FLACExtractor.h"
 #include "include/AACExtractor.h"
+#include "include/MidiExtractor.h"
 
 #include "matroska/MatroskaExtractor.h"
 
@@ -116,6 +117,8 @@
         ret = new AACExtractor(source, meta);
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2PS)) {
         ret = new MPEG2PSExtractor(source);
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MIDI)) {
+        ret = new MidiExtractor(source);
     }
 
     if (ret != NULL) {
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index c7c6f34..b13877d 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -38,21 +38,6 @@
 
 namespace android {
 
-MediaMuxer::MediaMuxer(const char *path, OutputFormat format)
-    : mFormat(format),
-      mState(UNINITIALIZED) {
-    if (format == OUTPUT_FORMAT_MPEG_4) {
-        mWriter = new MPEG4Writer(path);
-    } else if (format == OUTPUT_FORMAT_WEBM) {
-        mWriter = new WebmWriter(path);
-    }
-
-    if (mWriter != NULL) {
-        mFileMeta = new MetaData;
-        mState = INITIALIZED;
-    }
-}
-
 MediaMuxer::MediaMuxer(int fd, OutputFormat format)
     : mFormat(format),
       mState(UNINITIALIZED) {
diff --git a/media/libstagefright/MidiExtractor.cpp b/media/libstagefright/MidiExtractor.cpp
new file mode 100644
index 0000000..66fab77
--- /dev/null
+++ b/media/libstagefright/MidiExtractor.cpp
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2014 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 "MidiExtractor"
+#include <utils/Log.h>
+
+#include "include/MidiExtractor.h"
+
+#include <media/MidiIoWrapper.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaSource.h>
+#include <libsonivox/eas_reverb.h>
+
+namespace android {
+
+// how many Sonivox output buffers to aggregate into one MediaBuffer
+static const int NUM_COMBINE_BUFFERS = 4;
+
+class MidiSource : public MediaSource {
+
+public:
+    MidiSource(
+            const sp<MidiEngine> &engine,
+            const sp<MetaData> &trackMetadata);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+protected:
+    virtual ~MidiSource();
+
+private:
+    sp<MidiEngine> mEngine;
+    sp<MetaData> mTrackMetadata;
+    bool mInitCheck;
+    bool mStarted;
+
+    status_t init();
+
+    // no copy constructor or assignment
+    MidiSource(const MidiSource &);
+    MidiSource &operator=(const MidiSource &);
+
+};
+
+
+// Midisource
+
+MidiSource::MidiSource(
+        const sp<MidiEngine> &engine,
+        const sp<MetaData> &trackMetadata)
+    : mEngine(engine),
+      mTrackMetadata(trackMetadata),
+      mInitCheck(false),
+      mStarted(false)
+{
+    ALOGV("MidiSource ctor");
+    mInitCheck = init();
+}
+
+MidiSource::~MidiSource()
+{
+    ALOGV("MidiSource dtor");
+    if (mStarted) {
+        stop();
+    }
+}
+
+status_t MidiSource::start(MetaData * /* params */)
+{
+    ALOGV("MidiSource::start");
+
+    CHECK(!mStarted);
+    mStarted = true;
+    mEngine->allocateBuffers();
+    return OK;
+}
+
+status_t MidiSource::stop()
+{
+    ALOGV("MidiSource::stop");
+
+    CHECK(mStarted);
+    mStarted = false;
+    mEngine->releaseBuffers();
+
+    return OK;
+}
+
+sp<MetaData> MidiSource::getFormat()
+{
+    return mTrackMetadata;
+}
+
+status_t MidiSource::read(
+        MediaBuffer **outBuffer, const ReadOptions *options)
+{
+    ALOGV("MidiSource::read");
+    MediaBuffer *buffer;
+    // process an optional seek request
+    int64_t seekTimeUs;
+    ReadOptions::SeekMode mode;
+    if ((NULL != options) && options->getSeekTo(&seekTimeUs, &mode)) {
+        if (seekTimeUs <= 0LL) {
+            seekTimeUs = 0LL;
+        }
+        mEngine->seekTo(seekTimeUs);
+    }
+    buffer = mEngine->readBuffer();
+    *outBuffer = buffer;
+    ALOGV("MidiSource::read %p done", this);
+    return buffer != NULL ? (status_t) OK : (status_t) ERROR_END_OF_STREAM;
+}
+
+status_t MidiSource::init()
+{
+    ALOGV("MidiSource::init");
+    return OK;
+}
+
+// MidiEngine
+
+MidiEngine::MidiEngine(const sp<DataSource> &dataSource,
+        const sp<MetaData> &fileMetadata,
+        const sp<MetaData> &trackMetadata) :
+            mGroup(NULL),
+            mEasData(NULL),
+            mEasHandle(NULL),
+            mEasConfig(NULL),
+            mIsInitialized(false) {
+    mIoWrapper = new MidiIoWrapper(dataSource);
+    // spin up a new EAS engine
+    EAS_I32 temp;
+    EAS_RESULT result = EAS_Init(&mEasData);
+
+    if (result == EAS_SUCCESS) {
+        result = EAS_OpenFile(mEasData, mIoWrapper->getLocator(), &mEasHandle);
+    }
+    if (result == EAS_SUCCESS) {
+        result = EAS_Prepare(mEasData, mEasHandle);
+    }
+    if (result == EAS_SUCCESS) {
+        result = EAS_ParseMetaData(mEasData, mEasHandle, &temp);
+    }
+
+    if (result != EAS_SUCCESS) {
+        return;
+    }
+
+    if (fileMetadata != NULL) {
+        fileMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MIDI);
+    }
+
+    if (trackMetadata != NULL) {
+        trackMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+        trackMetadata->setInt64(kKeyDuration, 1000ll * temp); // milli->micro
+        mEasConfig = EAS_Config();
+        trackMetadata->setInt32(kKeySampleRate, mEasConfig->sampleRate);
+        trackMetadata->setInt32(kKeyChannelCount, mEasConfig->numChannels);
+    }
+    mIsInitialized = true;
+}
+
+MidiEngine::~MidiEngine() {
+    if (mEasHandle) {
+        EAS_CloseFile(mEasData, mEasHandle);
+    }
+    if (mEasData) {
+        EAS_Shutdown(mEasData);
+    }
+    delete mGroup;
+
+}
+
+status_t MidiEngine::initCheck() {
+    return mIsInitialized ? OK : UNKNOWN_ERROR;
+}
+
+status_t MidiEngine::allocateBuffers() {
+    // select reverb preset and enable
+    EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER);
+    EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE);
+
+    mGroup = new MediaBufferGroup;
+    int bufsize = sizeof(EAS_PCM)
+            * mEasConfig->mixBufferSize * mEasConfig->numChannels * NUM_COMBINE_BUFFERS;
+    ALOGV("using %d byte buffer", bufsize);
+    mGroup->add_buffer(new MediaBuffer(bufsize));
+    return OK;
+}
+
+status_t MidiEngine::releaseBuffers() {
+    delete mGroup;
+    mGroup = NULL;
+    return OK;
+}
+
+status_t MidiEngine::seekTo(int64_t positionUs) {
+    ALOGV("seekTo %lld", positionUs);
+    EAS_RESULT result = EAS_Locate(mEasData, mEasHandle, positionUs / 1000, false);
+    return result == EAS_SUCCESS ? OK : UNKNOWN_ERROR;
+}
+
+MediaBuffer* MidiEngine::readBuffer() {
+    EAS_STATE state;
+    EAS_State(mEasData, mEasHandle, &state);
+    if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) {
+        return NULL;
+    }
+    MediaBuffer *buffer;
+    status_t err = mGroup->acquire_buffer(&buffer);
+    if (err != OK) {
+        ALOGE("readBuffer: no buffer");
+        return NULL;
+    }
+    EAS_I32 timeMs;
+    EAS_GetLocation(mEasData, mEasHandle, &timeMs);
+    int64_t timeUs = 1000ll * timeMs;
+    buffer->meta_data()->setInt64(kKeyTime, timeUs);
+
+    EAS_PCM* p = (EAS_PCM*) buffer->data();
+    int numBytesOutput = 0;
+    for (int i = 0; i < NUM_COMBINE_BUFFERS; i++) {
+        EAS_I32 numRendered;
+        EAS_RESULT result = EAS_Render(mEasData, p, mEasConfig->mixBufferSize, &numRendered);
+        if (result != EAS_SUCCESS) {
+            ALOGE("EAS_Render returned %ld", result);
+            break;
+        }
+        p += numRendered * mEasConfig->numChannels;
+        numBytesOutput += numRendered * mEasConfig->numChannels * sizeof(EAS_PCM);
+    }
+    buffer->set_range(0, numBytesOutput);
+    ALOGV("readBuffer: returning %zd in buffer %p", buffer->range_length(), buffer);
+    return buffer;
+}
+
+
+// MidiExtractor
+
+MidiExtractor::MidiExtractor(
+        const sp<DataSource> &dataSource)
+    : mDataSource(dataSource),
+      mInitCheck(false)
+{
+    ALOGV("MidiExtractor ctor");
+    mFileMetadata = new MetaData;
+    mTrackMetadata = new MetaData;
+    mEngine = new MidiEngine(mDataSource, mFileMetadata, mTrackMetadata);
+    mInitCheck = mEngine->initCheck();
+}
+
+MidiExtractor::~MidiExtractor()
+{
+    ALOGV("MidiExtractor dtor");
+}
+
+size_t MidiExtractor::countTracks()
+{
+    return mInitCheck == OK ? 1 : 0;
+}
+
+sp<MediaSource> MidiExtractor::getTrack(size_t index)
+{
+    if (mInitCheck != OK || index > 0) {
+        return NULL;
+    }
+    return new MidiSource(mEngine, mTrackMetadata);
+}
+
+sp<MetaData> MidiExtractor::getTrackMetaData(
+        size_t index, uint32_t /* flags */) {
+    ALOGV("MidiExtractor::getTrackMetaData");
+    if (mInitCheck != OK || index > 0) {
+        return NULL;
+    }
+    return mTrackMetadata;
+}
+
+sp<MetaData> MidiExtractor::getMetaData()
+{
+    ALOGV("MidiExtractor::getMetaData");
+    return mFileMetadata;
+}
+
+// Sniffer
+
+bool SniffMidi(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        sp<AMessage> *)
+{
+    sp<MidiEngine> p = new MidiEngine(source, NULL, NULL);
+    if (p->initCheck() == OK) {
+        *mimeType = MEDIA_MIMETYPE_AUDIO_MIDI;
+        *confidence = 0.8;
+        ALOGV("SniffMidi: yes");
+        return true;
+    }
+    ALOGV("SniffMidi: no");
+    return false;
+
+}
+
+}  // namespace android
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index bd0a41d..8d70e50 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -226,7 +226,7 @@
     mLooper->start(false /* runOnCallingThread */, true /* canCallJava */);
 
     Mutex::Autolock autoLock(mLock);
-    (new AMessage(kWhatFetchMore, mReflector->id()))->post();
+    (new AMessage(kWhatFetchMore, mReflector))->post();
 }
 
 NuCachedSource2::~NuCachedSource2() {
@@ -354,7 +354,7 @@
     Mutex::Autolock autoLock(mLock);
 
     if (n == 0 || mDisconnecting) {
-        ALOGI("ERROR_END_OF_STREAM");
+        ALOGI("caching reached eos.");
 
         mNumRetriesLeft = 0;
         mFinalStatus = ERROR_END_OF_STREAM;
@@ -433,7 +433,7 @@
         delayUs = 100000ll;
     }
 
-    (new AMessage(kWhatFetchMore, mReflector->id()))->post(delayUs);
+    (new AMessage(kWhatFetchMore, mReflector))->post(delayUs);
 }
 
 void NuCachedSource2::onRead(const sp<AMessage> &msg) {
@@ -522,7 +522,7 @@
         return size;
     }
 
-    sp<AMessage> msg = new AMessage(kWhatRead, mReflector->id());
+    sp<AMessage> msg = new AMessage(kWhatRead, mReflector);
     msg->setInt64("offset", offset);
     msg->setPointer("data", data);
     msg->setSize("size", size);
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index ca031aa..230c1f7 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -37,7 +37,7 @@
     MuxOMX(const sp<IOMX> &remoteOMX);
     virtual ~MuxOMX();
 
-    virtual IBinder *onAsBinder() { return mRemoteOMX->asBinder().get(); }
+    virtual IBinder *onAsBinder() { return IInterface::asBinder(mRemoteOMX).get(); }
 
     virtual bool livesLocally(node_id node, pid_t pid);
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 288e07a..ea19ab2 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -47,10 +47,11 @@
 #include <media/stagefright/SkipCutBuffer.h>
 #include <utils/Vector.h>
 
-#include <OMX_Audio.h>
 #include <OMX_AudioExt.h>
 #include <OMX_Component.h>
 #include <OMX_IndexExt.h>
+#include <OMX_VideoExt.h>
+#include <OMX_AsString.h>
 
 #include "include/avc_utils.h"
 
@@ -100,10 +101,10 @@
 #undef FACTORY_CREATE_ENCODER
 #undef FACTORY_REF
 
-#define CODEC_LOGI(x, ...) ALOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
-#define CODEC_LOGV(x, ...) ALOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
-#define CODEC_LOGW(x, ...) ALOGW("[%s] "x, mComponentName, ##__VA_ARGS__)
-#define CODEC_LOGE(x, ...) ALOGE("[%s] "x, mComponentName, ##__VA_ARGS__)
+#define CODEC_LOGI(x, ...) ALOGI("[%s] " x, mComponentName, ##__VA_ARGS__)
+#define CODEC_LOGV(x, ...) ALOGV("[%s] " x, mComponentName, ##__VA_ARGS__)
+#define CODEC_LOGW(x, ...) ALOGW("[%s] " x, mComponentName, ##__VA_ARGS__)
+#define CODEC_LOGE(x, ...) ALOGE("[%s] " x, mComponentName, ##__VA_ARGS__)
 
 struct OMXCodecObserver : public BnOMXObserver {
     OMXCodecObserver() {
@@ -450,7 +451,7 @@
     // assertion, let's be lenient for now...
     // CHECK((ptr[4] >> 2) == 0x3f);  // reserved
 
-    size_t lengthSize = 1 + (ptr[4] & 3);
+    size_t lengthSize __unused = 1 + (ptr[4] & 3);
 
     // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
     // violates it...
@@ -2005,7 +2006,6 @@
 OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
     // Dequeue the next buffer from the native window.
     ANativeWindowBuffer* buf;
-    int fenceFd = -1;
     int err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
     if (err != 0) {
       CODEC_LOGE("dequeueBuffer failed w/ error 0x%08x", err);
@@ -2110,7 +2110,6 @@
     // on the screen and then been replaced, so an previous video frames are
     // guaranteed NOT to be currently displayed.
     for (int i = 0; i < numBufs + 1; i++) {
-        int fenceFd = -1;
         err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
         if (err != NO_ERROR) {
             ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
@@ -4078,220 +4077,6 @@
     CHECK(!"should not be here.");
 }
 
-static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
-    static const char *kNames[] = {
-        "OMX_IMAGE_CodingUnused",
-        "OMX_IMAGE_CodingAutoDetect",
-        "OMX_IMAGE_CodingJPEG",
-        "OMX_IMAGE_CodingJPEG2K",
-        "OMX_IMAGE_CodingEXIF",
-        "OMX_IMAGE_CodingTIFF",
-        "OMX_IMAGE_CodingGIF",
-        "OMX_IMAGE_CodingPNG",
-        "OMX_IMAGE_CodingLZW",
-        "OMX_IMAGE_CodingBMP",
-    };
-
-    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
-    if (type < 0 || (size_t)type >= numNames) {
-        return "UNKNOWN";
-    } else {
-        return kNames[type];
-    }
-}
-
-static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
-    static const char *kNames[] = {
-        "OMX_COLOR_FormatUnused",
-        "OMX_COLOR_FormatMonochrome",
-        "OMX_COLOR_Format8bitRGB332",
-        "OMX_COLOR_Format12bitRGB444",
-        "OMX_COLOR_Format16bitARGB4444",
-        "OMX_COLOR_Format16bitARGB1555",
-        "OMX_COLOR_Format16bitRGB565",
-        "OMX_COLOR_Format16bitBGR565",
-        "OMX_COLOR_Format18bitRGB666",
-        "OMX_COLOR_Format18bitARGB1665",
-        "OMX_COLOR_Format19bitARGB1666",
-        "OMX_COLOR_Format24bitRGB888",
-        "OMX_COLOR_Format24bitBGR888",
-        "OMX_COLOR_Format24bitARGB1887",
-        "OMX_COLOR_Format25bitARGB1888",
-        "OMX_COLOR_Format32bitBGRA8888",
-        "OMX_COLOR_Format32bitARGB8888",
-        "OMX_COLOR_FormatYUV411Planar",
-        "OMX_COLOR_FormatYUV411PackedPlanar",
-        "OMX_COLOR_FormatYUV420Planar",
-        "OMX_COLOR_FormatYUV420PackedPlanar",
-        "OMX_COLOR_FormatYUV420SemiPlanar",
-        "OMX_COLOR_FormatYUV422Planar",
-        "OMX_COLOR_FormatYUV422PackedPlanar",
-        "OMX_COLOR_FormatYUV422SemiPlanar",
-        "OMX_COLOR_FormatYCbYCr",
-        "OMX_COLOR_FormatYCrYCb",
-        "OMX_COLOR_FormatCbYCrY",
-        "OMX_COLOR_FormatCrYCbY",
-        "OMX_COLOR_FormatYUV444Interleaved",
-        "OMX_COLOR_FormatRawBayer8bit",
-        "OMX_COLOR_FormatRawBayer10bit",
-        "OMX_COLOR_FormatRawBayer8bitcompressed",
-        "OMX_COLOR_FormatL2",
-        "OMX_COLOR_FormatL4",
-        "OMX_COLOR_FormatL8",
-        "OMX_COLOR_FormatL16",
-        "OMX_COLOR_FormatL24",
-        "OMX_COLOR_FormatL32",
-        "OMX_COLOR_FormatYUV420PackedSemiPlanar",
-        "OMX_COLOR_FormatYUV422PackedSemiPlanar",
-        "OMX_COLOR_Format18BitBGR666",
-        "OMX_COLOR_Format24BitARGB6666",
-        "OMX_COLOR_Format24BitABGR6666",
-    };
-
-    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
-    if (type == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
-        return "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar";
-    } else if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
-        return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
-    } else if (type < 0 || (size_t)type >= numNames) {
-        return "UNKNOWN";
-    } else {
-        return kNames[type];
-    }
-}
-
-static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
-    static const char *kNames[] = {
-        "OMX_VIDEO_CodingUnused",
-        "OMX_VIDEO_CodingAutoDetect",
-        "OMX_VIDEO_CodingMPEG2",
-        "OMX_VIDEO_CodingH263",
-        "OMX_VIDEO_CodingMPEG4",
-        "OMX_VIDEO_CodingWMV",
-        "OMX_VIDEO_CodingRV",
-        "OMX_VIDEO_CodingAVC",
-        "OMX_VIDEO_CodingMJPEG",
-    };
-
-    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
-    if (type < 0 || (size_t)type >= numNames) {
-        return "UNKNOWN";
-    } else {
-        return kNames[type];
-    }
-}
-
-static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
-    static const char *kNames[] = {
-        "OMX_AUDIO_CodingUnused",
-        "OMX_AUDIO_CodingAutoDetect",
-        "OMX_AUDIO_CodingPCM",
-        "OMX_AUDIO_CodingADPCM",
-        "OMX_AUDIO_CodingAMR",
-        "OMX_AUDIO_CodingGSMFR",
-        "OMX_AUDIO_CodingGSMEFR",
-        "OMX_AUDIO_CodingGSMHR",
-        "OMX_AUDIO_CodingPDCFR",
-        "OMX_AUDIO_CodingPDCEFR",
-        "OMX_AUDIO_CodingPDCHR",
-        "OMX_AUDIO_CodingTDMAFR",
-        "OMX_AUDIO_CodingTDMAEFR",
-        "OMX_AUDIO_CodingQCELP8",
-        "OMX_AUDIO_CodingQCELP13",
-        "OMX_AUDIO_CodingEVRC",
-        "OMX_AUDIO_CodingSMV",
-        "OMX_AUDIO_CodingG711",
-        "OMX_AUDIO_CodingG723",
-        "OMX_AUDIO_CodingG726",
-        "OMX_AUDIO_CodingG729",
-        "OMX_AUDIO_CodingAAC",
-        "OMX_AUDIO_CodingMP3",
-        "OMX_AUDIO_CodingSBC",
-        "OMX_AUDIO_CodingVORBIS",
-        "OMX_AUDIO_CodingOPUS",
-        "OMX_AUDIO_CodingWMA",
-        "OMX_AUDIO_CodingRA",
-        "OMX_AUDIO_CodingMIDI",
-    };
-
-    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
-    if (type < 0 || (size_t)type >= numNames) {
-        return "UNKNOWN";
-    } else {
-        return kNames[type];
-    }
-}
-
-static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
-    static const char *kNames[] = {
-        "OMX_AUDIO_PCMModeLinear",
-        "OMX_AUDIO_PCMModeALaw",
-        "OMX_AUDIO_PCMModeMULaw",
-    };
-
-    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
-    if (type < 0 || (size_t)type >= numNames) {
-        return "UNKNOWN";
-    } else {
-        return kNames[type];
-    }
-}
-
-static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
-    static const char *kNames[] = {
-        "OMX_AUDIO_AMRBandModeUnused",
-        "OMX_AUDIO_AMRBandModeNB0",
-        "OMX_AUDIO_AMRBandModeNB1",
-        "OMX_AUDIO_AMRBandModeNB2",
-        "OMX_AUDIO_AMRBandModeNB3",
-        "OMX_AUDIO_AMRBandModeNB4",
-        "OMX_AUDIO_AMRBandModeNB5",
-        "OMX_AUDIO_AMRBandModeNB6",
-        "OMX_AUDIO_AMRBandModeNB7",
-        "OMX_AUDIO_AMRBandModeWB0",
-        "OMX_AUDIO_AMRBandModeWB1",
-        "OMX_AUDIO_AMRBandModeWB2",
-        "OMX_AUDIO_AMRBandModeWB3",
-        "OMX_AUDIO_AMRBandModeWB4",
-        "OMX_AUDIO_AMRBandModeWB5",
-        "OMX_AUDIO_AMRBandModeWB6",
-        "OMX_AUDIO_AMRBandModeWB7",
-        "OMX_AUDIO_AMRBandModeWB8",
-    };
-
-    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
-    if (type < 0 || (size_t)type >= numNames) {
-        return "UNKNOWN";
-    } else {
-        return kNames[type];
-    }
-}
-
-static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
-    static const char *kNames[] = {
-        "OMX_AUDIO_AMRFrameFormatConformance",
-        "OMX_AUDIO_AMRFrameFormatIF1",
-        "OMX_AUDIO_AMRFrameFormatIF2",
-        "OMX_AUDIO_AMRFrameFormatFSF",
-        "OMX_AUDIO_AMRFrameFormatRTPPayload",
-        "OMX_AUDIO_AMRFrameFormatITU",
-    };
-
-    size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
-    if (type < 0 || (size_t)type >= numNames) {
-        return "UNKNOWN";
-    } else {
-        return kNames[type];
-    }
-}
-
 void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
@@ -4322,10 +4107,10 @@
             printf("  nStride = %" PRIu32 "\n", imageDef->nStride);
 
             printf("  eCompressionFormat = %s\n",
-                   imageCompressionFormatString(imageDef->eCompressionFormat));
+                   asString(imageDef->eCompressionFormat));
 
             printf("  eColorFormat = %s\n",
-                   colorFormatString(imageDef->eColorFormat));
+                   asString(imageDef->eColorFormat));
 
             break;
         }
@@ -4341,10 +4126,10 @@
             printf("  nStride = %" PRIu32 "\n", videoDef->nStride);
 
             printf("  eCompressionFormat = %s\n",
-                   videoCompressionFormatString(videoDef->eCompressionFormat));
+                   asString(videoDef->eCompressionFormat));
 
             printf("  eColorFormat = %s\n",
-                   colorFormatString(videoDef->eColorFormat));
+                   asString(videoDef->eColorFormat));
 
             break;
         }
@@ -4356,7 +4141,7 @@
             printf("\n");
             printf("  // Audio\n");
             printf("  eEncoding = %s\n",
-                   audioCodingTypeString(audioDef->eEncoding));
+                   asString(audioDef->eEncoding));
 
             if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
                 OMX_AUDIO_PARAM_PCMMODETYPE params;
@@ -4376,7 +4161,7 @@
                        params.eNumData == OMX_NumericalDataSigned
                         ? "signed" : "unsigned");
 
-                printf("  ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
+                printf("  ePCMMode = %s\n", asString(params.ePCMMode));
             } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
                 OMX_AUDIO_PARAM_AMRTYPE amr;
                 InitOMXParams(&amr);
@@ -4388,9 +4173,9 @@
 
                 printf("  nChannels = %" PRIu32 "\n", amr.nChannels);
                 printf("  eAMRBandMode = %s\n",
-                        amrBandModeString(amr.eAMRBandMode));
+                        asString(amr.eAMRBandMode));
                 printf("  eAMRFrameFormat = %s\n",
-                        amrFrameFormatString(amr.eAMRFrameFormat));
+                        asString(amr.eAMRFrameFormat));
             }
 
             break;
@@ -4699,12 +4484,7 @@
         const char *componentName, const char *mime,
         bool isEncoder,
         CodecCapabilities *caps) {
-    if (strncmp(componentName, "OMX.", 4)) {
-        // Not an OpenMax component but a software codec.
-        caps->mFlags = 0;
-        caps->mComponentName = componentName;
-        return OK;
-    }
+    bool isVideo = !strncasecmp(mime, "video/", 6);
 
     sp<OMXCodecObserver> observer = new OMXCodecObserver;
     IOMX::node_id node;
@@ -4719,59 +4499,63 @@
     caps->mFlags = 0;
     caps->mComponentName = componentName;
 
-    OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
-    InitOMXParams(&param);
+    // NOTE: OMX does not provide a way to query AAC profile support
+    if (isVideo) {
+        OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+        InitOMXParams(&param);
 
-    param.nPortIndex = !isEncoder ? 0 : 1;
+        param.nPortIndex = !isEncoder ? 0 : 1;
 
-    for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
-        err = omx->getParameter(
-                node, OMX_IndexParamVideoProfileLevelQuerySupported,
-                &param, sizeof(param));
+        for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
+            err = omx->getParameter(
+                    node, OMX_IndexParamVideoProfileLevelQuerySupported,
+                    &param, sizeof(param));
 
-        if (err != OK) {
-            break;
+            if (err != OK) {
+                break;
+            }
+
+            CodecProfileLevel profileLevel;
+            profileLevel.mProfile = param.eProfile;
+            profileLevel.mLevel = param.eLevel;
+
+            caps->mProfileLevels.push(profileLevel);
         }
 
-        CodecProfileLevel profileLevel;
-        profileLevel.mProfile = param.eProfile;
-        profileLevel.mLevel = param.eLevel;
+        // Color format query
+        // return colors in the order reported by the OMX component
+        // prefix "flexible" standard ones with the flexible equivalent
+        OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
+        InitOMXParams(&portFormat);
+        portFormat.nPortIndex = !isEncoder ? 1 : 0;
+        for (portFormat.nIndex = 0;; ++portFormat.nIndex)  {
+            err = omx->getParameter(
+                    node, OMX_IndexParamVideoPortFormat,
+                    &portFormat, sizeof(portFormat));
+            if (err != OK) {
+                break;
+            }
 
-        caps->mProfileLevels.push(profileLevel);
-    }
-
-    // Color format query
-    // return colors in the order reported by the OMX component
-    // prefix "flexible" standard ones with the flexible equivalent
-    OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
-    InitOMXParams(&portFormat);
-    portFormat.nPortIndex = !isEncoder ? 1 : 0;
-    for (portFormat.nIndex = 0;; ++portFormat.nIndex)  {
-        err = omx->getParameter(
-                node, OMX_IndexParamVideoPortFormat,
-                &portFormat, sizeof(portFormat));
-        if (err != OK) {
-            break;
-        }
-
-        OMX_U32 flexibleEquivalent;
-        if (ACodec::isFlexibleColorFormat(
-                    omx, node, portFormat.eColorFormat, &flexibleEquivalent)) {
-            bool marked = false;
-            for (size_t i = 0; i < caps->mColorFormats.size(); i++) {
-                if (caps->mColorFormats.itemAt(i) == flexibleEquivalent) {
-                    marked = true;
-                    break;
+            OMX_U32 flexibleEquivalent;
+            if (ACodec::isFlexibleColorFormat(
+                        omx, node, portFormat.eColorFormat, false /* usingNativeWindow */,
+                        &flexibleEquivalent)) {
+                bool marked = false;
+                for (size_t i = 0; i < caps->mColorFormats.size(); i++) {
+                    if (caps->mColorFormats.itemAt(i) == flexibleEquivalent) {
+                        marked = true;
+                        break;
+                    }
+                }
+                if (!marked) {
+                    caps->mColorFormats.push(flexibleEquivalent);
                 }
             }
-            if (!marked) {
-                caps->mColorFormats.push(flexibleEquivalent);
-            }
+            caps->mColorFormats.push(portFormat.eColorFormat);
         }
-        caps->mColorFormats.push(portFormat.eColorFormat);
     }
 
-    if (!isEncoder && !strncmp(mime, "video/", 6)) {
+    if (isVideo && !isEncoder) {
         if (omx->storeMetaDataInBuffers(
                     node, 1 /* port index */, OMX_TRUE) == OK ||
             omx->prepareForAdaptivePlayback(
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 821bd81..6e32494 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -38,6 +38,7 @@
     int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
     int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
     int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
+    long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
 }
 
 namespace android {
@@ -75,7 +76,7 @@
 
     status_t seekToTime(int64_t timeUs);
     status_t seekToOffset(off64_t offset);
-    status_t readNextPacket(MediaBuffer **buffer);
+    status_t readNextPacket(MediaBuffer **buffer, bool conf);
 
     status_t init();
 
@@ -84,6 +85,8 @@
 private:
     struct Page {
         uint64_t mGranulePosition;
+        int32_t mPrevPacketSize;
+        uint64_t mPrevPacketPos;
         uint32_t mSerialNo;
         uint32_t mPageNo;
         uint8_t mFlags;
@@ -121,6 +124,8 @@
     status_t verifyHeader(
             MediaBuffer *buffer, uint8_t type);
 
+    int32_t packetBlockSize(MediaBuffer *buffer);
+
     void parseFileMetaData();
 
     status_t findPrevGranulePosition(off64_t pageOffset, uint64_t *granulePos);
@@ -180,7 +185,7 @@
     }
 
     MediaBuffer *packet;
-    status_t err = mExtractor->mImpl->readNextPacket(&packet);
+    status_t err = mExtractor->mImpl->readNextPacket(&packet, /* conf = */ false);
 
     if (err != OK) {
         return err;
@@ -373,6 +378,7 @@
     mFirstPacketInPage = true;
     mCurrentPageSamples = 0;
     mCurrentPage.mNumSegments = 0;
+    mCurrentPage.mPrevPacketSize = -1;
     mNextLaceIndex = 0;
 
     // XXX what if new page continues packet from last???
@@ -451,7 +457,7 @@
     return sizeof(header) + page->mNumSegments + totalSize;
 }
 
-status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) {
+status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out, bool conf) {
     *out = NULL;
 
     MediaBuffer *buffer = NULL;
@@ -489,16 +495,6 @@
                 tmp->set_range(0, buffer->range_length());
                 buffer->release();
             } else {
-                // XXX Not only is this not technically the correct time for
-                // this packet, we also stamp every packet in this page
-                // with the same time. This needs fixing later.
-
-                if (mVi.rate) {
-                    // Rate may not have been initialized yet if we're currently
-                    // reading the configuration packets...
-                    // Fortunately, the timestamp doesn't matter for those.
-                    timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate;
-                }
                 tmp->set_range(0, 0);
             }
             buffer = tmp;
@@ -521,16 +517,32 @@
             if (gotFullPacket) {
                 // We've just read the entire packet.
 
-                if (timeUs >= 0) {
-                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
-                }
-
                 if (mFirstPacketInPage) {
                     buffer->meta_data()->setInt32(
                             kKeyValidSamples, mCurrentPageSamples);
                     mFirstPacketInPage = false;
                 }
 
+                // ignore timestamp for configuration packets
+                if (!conf) {
+                    int32_t curBlockSize = packetBlockSize(buffer);
+                    if (mCurrentPage.mPrevPacketSize < 0) {
+                        mCurrentPage.mPrevPacketSize = curBlockSize;
+                        mCurrentPage.mPrevPacketPos =
+                                mCurrentPage.mGranulePosition - mCurrentPageSamples;
+                        timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
+                    } else {
+                        // The effective block size is the average of the two overlapped blocks
+                        int32_t actualBlockSize =
+                                (curBlockSize + mCurrentPage.mPrevPacketSize) / 2;
+                        timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
+                        // The actual size output by the decoder will be half the effective
+                        // size, due to the overlap
+                        mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
+                        mCurrentPage.mPrevPacketSize = curBlockSize;
+                    }
+                    buffer->meta_data()->setInt64(kKeyTime, timeUs);
+                }
                 *out = buffer;
 
                 return OK;
@@ -591,7 +603,7 @@
 
     MediaBuffer *packet;
     status_t err;
-    if ((err = readNextPacket(&packet)) != OK) {
+    if ((err = readNextPacket(&packet, /* conf = */ true)) != OK) {
         return err;
     }
     ALOGV("read packet of size %zu\n", packet->range_length());
@@ -602,7 +614,7 @@
         return err;
     }
 
-    if ((err = readNextPacket(&packet)) != OK) {
+    if ((err = readNextPacket(&packet, /* conf = */ true)) != OK) {
         return err;
     }
     ALOGV("read packet of size %zu\n", packet->range_length());
@@ -613,7 +625,7 @@
         return err;
     }
 
-    if ((err = readNextPacket(&packet)) != OK) {
+    if ((err = readNextPacket(&packet, /* conf = */ true)) != OK) {
         return err;
     }
     ALOGV("read packet of size %zu\n", packet->range_length());
@@ -686,6 +698,35 @@
     }
 }
 
+int32_t MyVorbisExtractor::packetBlockSize(MediaBuffer *buffer) {
+    const uint8_t *data =
+        (const uint8_t *)buffer->data() + buffer->range_offset();
+
+    size_t size = buffer->range_length();
+
+    ogg_buffer buf;
+    buf.data = (uint8_t *)data;
+    buf.size = size;
+    buf.refcount = 1;
+    buf.ptr.owner = NULL;
+
+    ogg_reference ref;
+    ref.buffer = &buf;
+    ref.begin = 0;
+    ref.length = size;
+    ref.next = NULL;
+
+    ogg_packet pack;
+    pack.packet = &ref;
+    pack.bytes = ref.length;
+    pack.b_o_s = 0;
+    pack.e_o_s = 0;
+    pack.granulepos = 0;
+    pack.packetno = 0;
+
+    return vorbis_packet_blocksize(&mVi, &pack);
+}
+
 status_t MyVorbisExtractor::verifyHeader(
         MediaBuffer *buffer, uint8_t type) {
     const uint8_t *data =
@@ -730,6 +771,10 @@
             ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
             ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
             ALOGV("window-bitrate = %ld", mVi.bitrate_window);
+            ALOGV("blocksizes: %d/%d",
+                    vorbis_info_blocksize(&mVi, 0),
+                    vorbis_info_blocksize(&mVi, 1)
+                    );
 
             off64_t size;
             if (mSource->getSize(&size) == OK) {
@@ -804,6 +849,7 @@
         { "TRACKNUMBER", kKeyCDTrackNumber },
         { "DISCNUMBER", kKeyDiscNumber },
         { "DATE", kKeyDate },
+        { "YEAR", kKeyYear },
         { "LYRICIST", kKeyWriter },
         { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
         { "ANDROID_LOOP", kKeyAutoLoop },
diff --git a/media/libstagefright/ProcessInfo.cpp b/media/libstagefright/ProcessInfo.cpp
new file mode 100644
index 0000000..b4172b3
--- /dev/null
+++ b/media/libstagefright/ProcessInfo.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "ProcessInfo"
+#include <utils/Log.h>
+
+#include <media/stagefright/ProcessInfo.h>
+
+#include <binder/IProcessInfoService.h>
+#include <binder/IServiceManager.h>
+
+namespace android {
+
+ProcessInfo::ProcessInfo() {}
+
+bool ProcessInfo::getPriority(int pid, int* priority) {
+    sp<IBinder> binder = defaultServiceManager()->getService(String16("processinfo"));
+    sp<IProcessInfoService> service = interface_cast<IProcessInfoService>(binder);
+
+    size_t length = 1;
+    int32_t states;
+    status_t err = service->getProcessStatesFromPids(length, &pid, &states);
+    if (err != OK) {
+        ALOGE("getProcessStatesFromPids failed");
+        return false;
+    }
+    ALOGV("pid %d states %d", pid, states);
+    if (states < 0) {
+        return false;
+    }
+
+    // Use process state as the priority. Lower the value, higher the priority.
+    *priority = states;
+    return true;
+}
+
+ProcessInfo::~ProcessInfo() {}
+
+}  // namespace android
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 4449d57..db33e83 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -28,9 +28,6 @@
 #include <media/mediametadataretriever.h>
 #include <private/media/VideoFrame.h>
 
-// Sonivox includes
-#include <libsonivox/eas.h>
-
 namespace android {
 
 StagefrightMediaScanner::StagefrightMediaScanner() {}
@@ -57,54 +54,6 @@
     return false;
 }
 
-static MediaScanResult HandleMIDI(
-        const char *filename, MediaScannerClient *client) {
-    // get the library configuration and do sanity check
-    const S_EAS_LIB_CONFIG* pLibConfig = EAS_Config();
-    if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
-        ALOGE("EAS library/header mismatch\n");
-        return MEDIA_SCAN_RESULT_ERROR;
-    }
-    EAS_I32 temp;
-
-    // spin up a new EAS engine
-    EAS_DATA_HANDLE easData = NULL;
-    EAS_HANDLE easHandle = NULL;
-    EAS_RESULT result = EAS_Init(&easData);
-    if (result == EAS_SUCCESS) {
-        EAS_FILE file;
-        file.path = filename;
-        file.fd = 0;
-        file.offset = 0;
-        file.length = 0;
-        result = EAS_OpenFile(easData, &file, &easHandle);
-    }
-    if (result == EAS_SUCCESS) {
-        result = EAS_Prepare(easData, easHandle);
-    }
-    if (result == EAS_SUCCESS) {
-        result = EAS_ParseMetaData(easData, easHandle, &temp);
-    }
-    if (easHandle) {
-        EAS_CloseFile(easData, easHandle);
-    }
-    if (easData) {
-        EAS_Shutdown(easData);
-    }
-
-    if (result != EAS_SUCCESS) {
-        return MEDIA_SCAN_RESULT_SKIPPED;
-    }
-
-    char buffer[20];
-    sprintf(buffer, "%ld", temp);
-    status_t status = client->addStringTag("duration", buffer);
-    if (status != OK) {
-        return MEDIA_SCAN_RESULT_ERROR;
-    }
-    return MEDIA_SCAN_RESULT_OK;
-}
-
 MediaScanResult StagefrightMediaScanner::processFile(
         const char *path, const char *mimeType,
         MediaScannerClient &client) {
@@ -130,18 +79,6 @@
         return MEDIA_SCAN_RESULT_SKIPPED;
     }
 
-    if (!strcasecmp(extension, ".mid")
-            || !strcasecmp(extension, ".smf")
-            || !strcasecmp(extension, ".imy")
-            || !strcasecmp(extension, ".midi")
-            || !strcasecmp(extension, ".xmf")
-            || !strcasecmp(extension, ".rtttl")
-            || !strcasecmp(extension, ".rtx")
-            || !strcasecmp(extension, ".ota")
-            || !strcasecmp(extension, ".mxmf")) {
-        return HandleMIDI(path, &client);
-    }
-
     sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
 
     int fd = open(path, O_RDONLY | O_LARGEFILE);
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 4e1c65c..e8abf48 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -26,6 +26,7 @@
 #include <media/hardware/MetadataBufferType.h>
 
 #include <ui/GraphicBuffer.h>
+#include <gui/BufferItem.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/IGraphicBufferAlloc.h>
 #include <OMX_Component.h>
@@ -290,7 +291,7 @@
     // TODO: mCurrentSlot can be made a bufferstate since there
     // can be more than one "current" slots.
 
-    BufferQueue::BufferItem item;
+    BufferItem item;
     // If the recording has started and the queue is empty, then just
     // wait here till the frames come in from the client side
     while (mStarted) {
@@ -448,7 +449,7 @@
 }
 
 // Part of the BufferQueue::ConsumerListener
-void SurfaceMediaSource::onFrameAvailable() {
+void SurfaceMediaSource::onFrameAvailable(const BufferItem& /* item */) {
     ALOGV("onFrameAvailable");
 
     sp<FrameAvailableListener> listener;
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index 1fdb244..7d15220 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -52,7 +52,7 @@
 TimedEventQueue::~TimedEventQueue() {
     stop();
     if (mPowerManager != 0) {
-        sp<IBinder> binder = mPowerManager->asBinder();
+        sp<IBinder> binder = IInterface::asBinder(mPowerManager);
         binder->unlinkToDeath(mDeathRecipient);
     }
 }
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 25afc5b..c0be136 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -181,14 +181,14 @@
 
         CHECK(size >= 7);
         CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
-        uint8_t profile = ptr[1];
-        uint8_t level = ptr[3];
+        uint8_t profile __unused = ptr[1];
+        uint8_t level __unused = ptr[3];
 
         // There is decodable content out there that fails the following
         // assertion, let's be lenient for now...
         // CHECK((ptr[4] >> 2) == 0x3f);  // reserved
 
-        size_t lengthSize = 1 + (ptr[4] & 3);
+        size_t lengthSize __unused = 1 + (ptr[4] & 3);
 
         // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
         // violates it...
@@ -257,8 +257,8 @@
 
         CHECK(size >= 7);
         CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
-        uint8_t profile = ptr[1] & 31;
-        uint8_t level = ptr[12];
+        uint8_t profile __unused = ptr[1] & 31;
+        uint8_t level __unused = ptr[12];
         ptr += 22;
         size -= 22;
 
@@ -344,6 +344,28 @@
         buffer->meta()->setInt32("csd", true);
         buffer->meta()->setInt64("timeUs", 0);
         msg->setBuffer("csd-0", buffer);
+
+        if (!meta->findData(kKeyOpusCodecDelay, &type, &data, &size)) {
+            return -EINVAL;
+        }
+
+        buffer = new ABuffer(size);
+        memcpy(buffer->data(), data, size);
+
+        buffer->meta()->setInt32("csd", true);
+        buffer->meta()->setInt64("timeUs", 0);
+        msg->setBuffer("csd-1", buffer);
+
+        if (!meta->findData(kKeyOpusSeekPreRoll, &type, &data, &size)) {
+            return -EINVAL;
+        }
+
+        buffer = new ABuffer(size);
+        memcpy(buffer->data(), data, size);
+
+        buffer->meta()->setInt32("csd", true);
+        buffer->meta()->setInt64("timeUs", 0);
+        msg->setBuffer("csd-2", buffer);
     }
 
     *format = msg;
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index a4a651d..335ac84 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -439,10 +439,6 @@
         maxBytesToRead = maxBytesAvailable;
     }
 
-    // read only integral amounts of audio unit frames.
-    const size_t inputUnitFrameSize = mNumChannels * mBitsPerSample / 8;
-    maxBytesToRead -= maxBytesToRead % inputUnitFrameSize;
-
     if (mWaveFormat == WAVE_FORMAT_MSGSM) {
         // Microsoft packs 2 frames into 65 bytes, rather than using separate 33-byte frames,
         // so read multiples of 65, and use smaller buffers to account for ~10:1 expansion ratio
@@ -450,6 +446,10 @@
             maxBytesToRead = 1024;
         }
         maxBytesToRead = (maxBytesToRead / 65) * 65;
+    } else {
+        // read only integral amounts of audio unit frames.
+        const size_t inputUnitFrameSize = mNumChannels * mBitsPerSample / 8;
+        maxBytesToRead -= maxBytesToRead % inputUnitFrameSize;
     }
 
     ssize_t n = mDataSource->readAt(
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index 38a1f6b..8ef2dca 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -26,6 +26,7 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
+#include <utils/misc.h>
 
 namespace android {
 
@@ -186,17 +187,31 @@
             if (aspect_ratio_idc == 255 /* extendedSAR */) {
                 sar_width = br.getBits(16);
                 sar_height = br.getBits(16);
-            } else if (aspect_ratio_idc > 0 && aspect_ratio_idc < 14) {
-                static const int32_t kFixedSARWidth[] = {
-                    1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160
+            } else {
+                static const struct { unsigned width, height; } kFixedSARs[] = {
+                        {   0,  0 }, // Invalid
+                        {   1,  1 },
+                        {  12, 11 },
+                        {  10, 11 },
+                        {  16, 11 },
+                        {  40, 33 },
+                        {  24, 11 },
+                        {  20, 11 },
+                        {  32, 11 },
+                        {  80, 33 },
+                        {  18, 11 },
+                        {  15, 11 },
+                        {  64, 33 },
+                        { 160, 99 },
+                        {   4,  3 },
+                        {   3,  2 },
+                        {   2,  1 },
                 };
 
-                static const int32_t kFixedSARHeight[] = {
-                    1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99
-                };
-
-                sar_width = kFixedSARWidth[aspect_ratio_idc - 1];
-                sar_height = kFixedSARHeight[aspect_ratio_idc - 1];
+                if (aspect_ratio_idc > 0 && aspect_ratio_idc < NELEM(kFixedSARs)) {
+                    sar_width = kFixedSARs[aspect_ratio_idc].width;
+                    sar_height = kFixedSARs[aspect_ratio_idc].height;
+                }
             }
         }
 
@@ -222,28 +237,25 @@
     *nalStart = NULL;
     *nalSize = 0;
 
-    if (size == 0) {
+    if (size < 3) {
         return -EAGAIN;
     }
 
-    // Skip any number of leading 0x00.
-
     size_t offset = 0;
-    while (offset < size && data[offset] == 0x00) {
-        ++offset;
-    }
-
-    if (offset == size) {
-        return -EAGAIN;
-    }
 
     // A valid startcode consists of at least two 0x00 bytes followed by 0x01.
-
-    if (offset < 2 || data[offset] != 0x01) {
-        return ERROR_MALFORMED;
+    for (; offset + 2 < size; ++offset) {
+        if (data[offset + 2] == 0x01 && data[offset] == 0x00
+                && data[offset + 1] == 0x00) {
+            break;
+        }
     }
-
-    ++offset;
+    if (offset + 2 >= size) {
+        *_data = &data[offset];
+        *_size = 2;
+        return -EAGAIN;
+    }
+    offset += 3;
 
     size_t startOffset = offset;
 
@@ -508,8 +520,8 @@
     CHECK_NE(video_object_type_indication,
              0x21u /* Fine Granularity Scalable */);
 
-    unsigned video_object_layer_verid;
-    unsigned video_object_layer_priority;
+    unsigned video_object_layer_verid __unused;
+    unsigned video_object_layer_priority __unused;
     if (br.getBits(1)) {
         video_object_layer_verid = br.getBits(4);
         video_object_layer_priority = br.getBits(3);
@@ -571,7 +583,7 @@
     unsigned video_object_layer_height = br.getBits(13);
     CHECK(br.getBits(1));  // marker_bit
 
-    unsigned interlaced = br.getBits(1);
+    unsigned interlaced __unused = br.getBits(1);
 
     *width = video_object_layer_width;
     *height = video_object_layer_height;
@@ -617,7 +629,7 @@
         return false;
     }
 
-    unsigned protection = (header >> 16) & 1;
+    unsigned protection __unused = (header >> 16) & 1;
 
     unsigned bitrate_index = (header >> 12) & 0x0f;
 
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 351ba1e..10937ec 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -623,7 +623,7 @@
                 } else {
                     int64_t currentTime = mBufferTimestamps.top();
                     currentTime += mStreamInfo->aacSamplesPerFrame *
-                            1000000ll / mStreamInfo->sampleRate;
+                            1000000ll / mStreamInfo->aacSampleRate;
                     mBufferTimestamps.add(currentTime);
                 }
             } else {
@@ -874,9 +874,9 @@
                         // adjust/interpolate next time stamp
                         *currentBufLeft -= decodedSize;
                         *nextTimeStamp += mStreamInfo->aacSamplesPerFrame *
-                                1000000ll / mStreamInfo->sampleRate;
+                                1000000ll / mStreamInfo->aacSampleRate;
                         ALOGV("adjusted nextTimeStamp/size to %lld/%d",
-                                *nextTimeStamp, *currentBufLeft);
+                                (long long) *nextTimeStamp, *currentBufLeft);
                     } else {
                         // move to next timestamp in list
                         if (mBufferTimestamps.size() > 0) {
@@ -885,7 +885,7 @@
                             mBufferSizes.removeAt(0);
                             currentBufLeft = &mBufferSizes.editItemAt(0);
                             ALOGV("moved to next time/size: %lld/%d",
-                                    *nextTimeStamp, *currentBufLeft);
+                                    (long long) *nextTimeStamp, *currentBufLeft);
                         }
                         // try to limit output buffer size to match input buffers
                         // (e.g when an input buffer contained 4 "sub" frames, output
@@ -975,6 +975,7 @@
         mBufferSizes.clear();
         mDecodedSizes.clear();
         mLastInHeader = NULL;
+        mEndOfInput = false;
     } else {
         int avail;
         while ((avail = outputDelayRingBufferSamplesAvailable()) > 0) {
@@ -989,12 +990,11 @@
             mOutputBufferCount++;
         }
         mOutputDelayRingBufferReadPos = mOutputDelayRingBufferWritePos;
+        mEndOfOutput = false;
     }
 }
 
 void SoftAAC2::drainDecoder() {
-    int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels;
-
     // flush decoder until outputDelay is compensated
     while (mOutputDelayCompensated > 0) {
         // a buffer big enough for MAX_CHANNEL_COUNT channels of decoded HE-AAC
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
index 8b5007e..bebb9dc 100644
--- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -214,8 +214,6 @@
 
 status_t AACEncoder::read(
         MediaBuffer **out, const ReadOptions *options) {
-    status_t err;
-
     *out = NULL;
 
     int64_t seekTimeUs;
diff --git a/media/libstagefright/codecs/aacenc/basic_op/basic_op.h b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h
index 5cd7e5f..bbc753b 100644
--- a/media/libstagefright/codecs/aacenc/basic_op/basic_op.h
+++ b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h
@@ -518,8 +518,6 @@
         return  ASM_L_shr( L_var1, -var2);
     }
 #else
-    Word32 L_var_out = 0L;
-
     if (var2 <= 0)
     {
         L_var1 = L_shr(L_var1, (Word16)-var2);
@@ -540,7 +538,6 @@
                 }
             }
             L_var1 <<= 1;
-            L_var_out = L_var1;
         }
     }
     return (L_var1);
diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
index 1d029fc..4fd16a1 100644
--- a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
+++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
@@ -245,10 +245,9 @@
 Word32 rsqrt(Word32 value,     /*!< Operand to square root (0.0 ... 1) */
              Word32 accuracy)  /*!< Number of valid bits that will be calculated */
 {
-    UNUSED(accuracy);
-
     Word32 root = 0;
 	Word32 scale;
+    UNUSED(accuracy);
 
 	if(value < 0)
 		return 0;
@@ -351,12 +350,11 @@
   UWord32 iPart;
   UWord32 fPart;
   Word32 res;
-  Word32 tmp, tmp2;
-  Word32 shift, shift2;
+  Word32 tmp;
 
-  tmp2 = -x;
-  iPart = tmp2 / y;
-  fPart = tmp2 - iPart*y;
+  tmp = -x;
+  iPart = tmp / y;
+  fPart = tmp - iPart*y;
   iPart = min(iPart,INT_BITS-1);
 
   res = pow2Table[(POW2_TABLE_SIZE*fPart)/y] >> iPart;
diff --git a/media/libstagefright/codecs/aacenc/src/aacenc.c b/media/libstagefright/codecs/aacenc/src/aacenc.c
index 40db92c..df17787 100644
--- a/media/libstagefright/codecs/aacenc/src/aacenc.c
+++ b/media/libstagefright/codecs/aacenc/src/aacenc.c
@@ -39,18 +39,20 @@
 VO_U32 VO_API voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA *pUserData)
 {
 	AAC_ENCODER*hAacEnc;
-	AACENC_CONFIG config;
 	int error;
 
 #ifdef USE_DEAULT_MEM
 	VO_MEM_OPERATOR voMemoprator;
 #endif
 	VO_MEM_OPERATOR *pMemOP;
+
+#ifdef USE_DEAULT_MEM
 	int interMem;
+        interMem = 0;
+#endif
 
         UNUSED(vType);
 
-	interMem = 0;
 	error = 0;
 
 	/* init the memory operator */
@@ -214,7 +216,7 @@
 	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
 	Word16 numAncDataBytes=0;
 	Word32  inbuflen;
-	int ret, length;
+	int length;
 	if(NULL == hAacEnc)
 		return VO_ERR_INVALID_ARG;
 
diff --git a/media/libstagefright/codecs/aacenc/src/aacenc_core.c b/media/libstagefright/codecs/aacenc/src/aacenc_core.c
index cecbc8f..de452d4 100644
--- a/media/libstagefright/codecs/aacenc/src/aacenc_core.c
+++ b/media/libstagefright/codecs/aacenc/src/aacenc_core.c
@@ -58,7 +58,6 @@
                      const  AACENC_CONFIG     config   /* pre-initialized config struct */
                      )
 {
-  Word32 i;
   Word32 error = 0;
   Word16 profile = 1;
 
diff --git a/media/libstagefright/codecs/aacenc/src/adj_thr.c b/media/libstagefright/codecs/aacenc/src/adj_thr.c
index 471631c..8b8be0e 100644
--- a/media/libstagefright/codecs/aacenc/src/adj_thr.c
+++ b/media/libstagefright/codecs/aacenc/src/adj_thr.c
@@ -96,7 +96,7 @@
                         MINSNR_ADAPT_PARAM *msaParam,
                         const Word16        nChannels)
 {
-  Word16 ch, sfb, sfbOffs, shift;
+  Word16 ch, sfb, sfbOffs;
   Word32 nSfb, avgEn;
   Word16 log_avgEn = 0;
   Word32 startRatio_x_avgEn = 0;
diff --git a/media/libstagefright/codecs/aacenc/src/bitbuffer.c b/media/libstagefright/codecs/aacenc/src/bitbuffer.c
index 0ce93d3..15eebd0 100644
--- a/media/libstagefright/codecs/aacenc/src/bitbuffer.c
+++ b/media/libstagefright/codecs/aacenc/src/bitbuffer.c
@@ -24,29 +24,6 @@
 
 /*****************************************************************************
 *
-* function name: updateBitBufWordPtr
-* description:  update Bit Buffer pointer
-*
-*****************************************************************************/
-static void updateBitBufWordPtr(HANDLE_BIT_BUF hBitBuf,
-                                UWord8 **pBitBufWord,
-                                Word16   cnt)
-{
-  *pBitBufWord += cnt;
-
-
-  if(*pBitBufWord > hBitBuf->pBitBufEnd) {
-    *pBitBufWord -= (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1);
-  }
-
-  if(*pBitBufWord < hBitBuf->pBitBufBase) {
-    *pBitBufWord += (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1);
-  }
-}
-
-
-/*****************************************************************************
-*
 * function name: CreateBitBuffer
 * description:  create and init Bit Buffer Management
 *
diff --git a/media/libstagefright/codecs/aacenc/src/bitenc.c b/media/libstagefright/codecs/aacenc/src/bitenc.c
index d1fd647..9c81204 100644
--- a/media/libstagefright/codecs/aacenc/src/bitenc.c
+++ b/media/libstagefright/codecs/aacenc/src/bitenc.c
@@ -547,7 +547,7 @@
     totFillBits = totFillBits - (3+4);
 
 
-    if ((cnt == (1<<4)-1)) {
+    if (cnt == (1<<4)-1) {
 
       esc_count = min( ((totFillBits >> 3) - ((1<<4)-1)), (1<<8)-1);
       WriteBits(hBitStream,esc_count,8);
diff --git a/media/libstagefright/codecs/aacenc/src/block_switch.c b/media/libstagefright/codecs/aacenc/src/block_switch.c
index c80538f..11bc7e7 100644
--- a/media/libstagefright/codecs/aacenc/src/block_switch.c
+++ b/media/libstagefright/codecs/aacenc/src/block_switch.c
@@ -30,9 +30,6 @@
 #define ENERGY_SHIFT (8 - 1)
 
 /**************** internal function prototypes ***********/
-static Word16
-IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[]);
-
 static Word32
 SrchMaxWithIndex(const Word32 *in, Word16 *index, Word16 n);
 
@@ -280,7 +277,7 @@
                         Word16 chIncrement,
                         Word16 windowLen)
 {
-  Word32 w, i, wOffset, tidx, ch;
+  Word32 w, i, tidx;
   Word32 accuUE, accuFE;
   Word32 tempUnfiltered;
   Word32 tempFiltered;
@@ -329,30 +326,6 @@
 }
 #endif
 
-/*****************************************************************************
-*
-* function name: IIRFilter
-* description:  calculate the iir-filter for an array
-* returns:      the result after iir-filter
-*
-**********************************************************************************/
-static Word16 IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[])
-{
-  Word32 accu1, accu2, accu3;
-  Word32 out;
-
-  accu1 = L_mpy_ls(coeff[1], in);
-  accu3 = accu1 - states[0];
-  accu2 = fixmul( coeff[0], states[1] );
-  out = accu3 - accu2;
-
-  states[0] = accu1;
-  states[1] = out;
-
-  return round16(out);
-}
-
-
 static Word16 synchronizedBlockTypeTable[4][4] = {
   /*                 LONG_WINDOW   START_WINDOW  SHORT_WINDOW  STOP_WINDOW */
   /* LONG_WINDOW  */{LONG_WINDOW,  START_WINDOW, SHORT_WINDOW, STOP_WINDOW},
diff --git a/media/libstagefright/codecs/aacenc/src/ms_stereo.c b/media/libstagefright/codecs/aacenc/src/ms_stereo.c
index 2e34f14..1e4b227 100644
--- a/media/libstagefright/codecs/aacenc/src/ms_stereo.c
+++ b/media/libstagefright/codecs/aacenc/src/ms_stereo.c
@@ -50,7 +50,6 @@
                         const Word16  sfbPerGroup,
                         const Word16  maxSfbPerGroup,
                         const Word16 *sfbOffset) {
-  Word32 temp;
   Word32 sfb,sfboffs, j;
   Word32 msMaskTrueSomewhere = 0;
   Word32 msMaskFalseSomewhere = 0;
diff --git a/media/libstagefright/codecs/aacenc/src/sf_estim.c b/media/libstagefright/codecs/aacenc/src/sf_estim.c
index bc320ec..78947e1 100644
--- a/media/libstagefright/codecs/aacenc/src/sf_estim.c
+++ b/media/libstagefright/codecs/aacenc/src/sf_estim.c
@@ -99,7 +99,7 @@
 {
 	Word32 sfbw, sfbw1;
 	Word32 i, j;
-	Word32 sfbOffs, sfb, shift;
+	Word32 sfbOffs, sfb;
 
 	sfbw = sfbw1 = 0;
 	for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup){
diff --git a/media/libstagefright/codecs/aacenc/src/tns.c b/media/libstagefright/codecs/aacenc/src/tns.c
index 5172612..27c3971 100644
--- a/media/libstagefright/codecs/aacenc/src/tns.c
+++ b/media/libstagefright/codecs/aacenc/src/tns.c
@@ -140,7 +140,7 @@
                                 Word16 active)              /*!< tns active flag */
 {
 
-  Word32 bitratePerChannel;
+  Word32 bitratePerChannel __unused;
   tC->maxOrder     = TNS_MAX_ORDER;
   tC->tnsStartFreq = 1275;
   tC->coefRes      = 4;
@@ -206,7 +206,7 @@
                                  PSY_CONFIGURATION_SHORT *pC, /*!< psy config struct */
                                  Word16 active)               /*!< tns active flag */
 {
-  Word32 bitratePerChannel;
+  Word32 bitratePerChannel __unused;
   tC->maxOrder     = TNS_MAX_ORDER_SHORT;
   tC->tnsStartFreq = 2750;
   tC->coefRes      = 3;
@@ -497,36 +497,6 @@
 
 /*****************************************************************************
 *
-* function name: m_pow2_cordic
-* description: Iterative power function
-*
-*	Calculates pow(2.0,x-1.0*(scale+1)) with INT_BITS bit precision
-*	using modified cordic algorithm
-* returns:     the result of pow2
-*
-*****************************************************************************/
-static Word32 m_pow2_cordic(Word32 x, Word16 scale)
-{
-  Word32 k;
-
-  Word32 accu_y = 0x40000000;
-  accu_y = L_shr(accu_y,scale);
-
-  for(k=1; k<INT_BITS; k++) {
-    const Word32 z = m_log2_table[k];
-
-    while(L_sub(x,z) >= 0) {
-
-      x = L_sub(x, z);
-      accu_y = L_add(accu_y, (accu_y >> k));
-    }
-  }
-  return(accu_y);
-}
-
-
-/*****************************************************************************
-*
 * function name: CalcWeightedSpectrum
 * description: Calculate weighted spectrum for LPC calculation
 *
diff --git a/media/libstagefright/codecs/aacenc/src/transform.c b/media/libstagefright/codecs/aacenc/src/transform.c
index a02336f..0080810 100644
--- a/media/libstagefright/codecs/aacenc/src/transform.c
+++ b/media/libstagefright/codecs/aacenc/src/transform.c
@@ -475,7 +475,6 @@
 	Word32 *winPtr;
 
 	Word32 delayBufferSf,timeSignalSf,minSf;
-	Word32 headRoom=0;
 
 	switch(blockType){
 
diff --git a/media/libstagefright/codecs/amrnb/common/Android.mk b/media/libstagefright/codecs/amrnb/common/Android.mk
index a2b3c8f..5e632a6 100644
--- a/media/libstagefright/codecs/amrnb/common/Android.mk
+++ b/media/libstagefright/codecs/amrnb/common/Android.mk
@@ -67,7 +67,7 @@
         $(LOCAL_PATH)/include
 
 LOCAL_CFLAGS := \
-        -DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF=
+        -D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF=
 
 LOCAL_CFLAGS += -Werror
 
diff --git a/media/libstagefright/codecs/amrnb/common/include/basic_op_c_equivalent.h b/media/libstagefright/codecs/amrnb/common/include/basic_op_c_equivalent.h
index 35638e3..c4e4d4f 100644
--- a/media/libstagefright/codecs/amrnb/common/include/basic_op_c_equivalent.h
+++ b/media/libstagefright/codecs/amrnb/common/include/basic_op_c_equivalent.h
@@ -115,7 +115,7 @@
      Returns:
         L_sum = 32-bit sum of L_var1 and L_var2 (Word32)
     */
-    static inline Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow)
+    static inline Word32 L_add(Word32 L_var1, Word32 L_var2, Flag *pOverflow)
     {
         Word32 L_sum;
 
@@ -154,8 +154,8 @@
      Returns:
         L_diff = 32-bit difference of L_var1 and L_var2 (Word32)
     */
-    static inline Word32 L_sub(register Word32 L_var1, register Word32 L_var2,
-                               register Flag *pOverflow)
+    static inline Word32 L_sub(Word32 L_var1, Word32 L_var2,
+                               Flag *pOverflow)
     {
         Word32 L_diff;
 
@@ -246,7 +246,7 @@
     */
     static inline Word32 L_mult(Word16 var1, Word16 var2, Flag *pOverflow)
     {
-        register Word32 L_product;
+        Word32 L_product;
 
         L_product = (Word32) var1 * var2;
 
@@ -452,7 +452,7 @@
     */
     static inline Word16 mult(Word16 var1, Word16 var2, Flag *pOverflow)
     {
-        register Word32 product;
+        Word32 product;
 
         product = ((Word32) var1 * var2) >> 15;
 
diff --git a/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp b/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp
index 4135f30..976b1a6 100644
--- a/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp
@@ -564,10 +564,10 @@
     Flag   *pOverflow   /* (i/o): overflow flag                              */
 )
 {
-    register Word16 i;
-    register Word16 j;
-    register Word16 nf;
-    register Word16 ip;
+    Word16 i;
+    Word16 j;
+    Word16 nf;
+    Word16 ip;
     Word16 xlow;
     Word16 ylow;
     Word16 xhigh;
diff --git a/media/libstagefright/codecs/amrnb/common/src/div_s.cpp b/media/libstagefright/codecs/amrnb/common/src/div_s.cpp
index f3bed7e..14d30c5 100644
--- a/media/libstagefright/codecs/amrnb/common/src/div_s.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/div_s.cpp
@@ -207,13 +207,13 @@
 /*----------------------------------------------------------------------------
 ; FUNCTION CODE
 ----------------------------------------------------------------------------*/
-Word16 div_s(register Word16 var1, register Word16 var2)
+Word16 div_s(Word16 var1, Word16 var2)
 {
     /*----------------------------------------------------------------------------
     ; Define all local variables
     ----------------------------------------------------------------------------*/
     Word16 var_out = 0;
-    register Word16 iteration;
+    Word16 iteration;
     Word32 L_num;
     Word32 L_denom;
     Word32 L_denom_by_2;
diff --git a/media/libstagefright/codecs/amrnb/common/src/gc_pred.cpp b/media/libstagefright/codecs/amrnb/common/src/gc_pred.cpp
index 3650f3c..1c8a700 100644
--- a/media/libstagefright/codecs/amrnb/common/src/gc_pred.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/gc_pred.cpp
@@ -477,9 +477,9 @@
     Flag   *pOverflow
 )
 {
-    register Word16 i;
-    register Word32 L_temp1, L_temp2;
-    register Word32 L_tmp;
+    Word16 i;
+    Word32 L_temp1, L_temp2;
+    Word32 L_tmp;
     Word32 ener_code;
     Word32 ener;
     Word16 exp, frac;
@@ -993,7 +993,7 @@
 )
 {
     Word16 av_pred_en;
-    register Word16 i;
+    Word16 i;
 
     /* do average in MR122 mode (log2() domain) */
     av_pred_en = 0;
diff --git a/media/libstagefright/codecs/amrnb/common/src/gmed_n.cpp b/media/libstagefright/codecs/amrnb/common/src/gmed_n.cpp
index be76241..2d3b9e4 100644
--- a/media/libstagefright/codecs/amrnb/common/src/gmed_n.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/gmed_n.cpp
@@ -185,9 +185,9 @@
     Word16 n        /* i : number of inputs    */
 )
 {
-    register Word16 i, j, ix = 0;
-    register Word16 max;
-    register Word16 medianIndex;
+    Word16 i, j, ix = 0;
+    Word16 max;
+    Word16 medianIndex;
     Word16  tmp[NMAX];
     Word16  tmp2[NMAX];
 
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_az.cpp b/media/libstagefright/codecs/amrnb/common/src/lsp_az.cpp
index 6b7b471..495359f 100644
--- a/media/libstagefright/codecs/amrnb/common/src/lsp_az.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/lsp_az.cpp
@@ -254,8 +254,8 @@
     Word32 *f,
     Flag   *pOverflow)
 {
-    register Word16 i;
-    register Word16 j;
+    Word16 i;
+    Word16 j;
 
     Word16 hi;
     Word16 lo;
@@ -511,8 +511,8 @@
     Flag  *pOverflow     /* (o)  : overflow flag                        */
 )
 {
-    register Word16 i;
-    register Word16 j;
+    Word16 i;
+    Word16 j;
 
     Word32 f1[6];
     Word32 f2[6];
diff --git a/media/libstagefright/codecs/amrnb/common/src/mult_r.cpp b/media/libstagefright/codecs/amrnb/common/src/mult_r.cpp
index 0777e68..7112b3d 100644
--- a/media/libstagefright/codecs/amrnb/common/src/mult_r.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/mult_r.cpp
@@ -190,7 +190,7 @@
 Word16 mult_r(Word16 var1, Word16 var2, Flag *pOverflow)
 {
 
-    register Word32 L_product_arr;
+    Word32 L_product_arr;
 
     L_product_arr = ((Word32) var1) * var2;              /* product */
     L_product_arr += (Word32) 0x00004000L;               /* round */
diff --git a/media/libstagefright/codecs/amrnb/common/src/norm_l.cpp b/media/libstagefright/codecs/amrnb/common/src/norm_l.cpp
index 132fed6..d8d1259 100644
--- a/media/libstagefright/codecs/amrnb/common/src/norm_l.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/norm_l.cpp
@@ -197,12 +197,12 @@
 ; FUNCTION CODE
 ----------------------------------------------------------------------------*/
 #if !( defined(PV_ARM_V5) || defined(PV_ARM_GCC_V5) )
-Word16 norm_l(register Word32 L_var1)
+Word16 norm_l(Word32 L_var1)
 {
     /*----------------------------------------------------------------------------
     ; Define all local variables
     ----------------------------------------------------------------------------*/
-    register Word16 var_out = 0;
+    Word16 var_out = 0;
 
     /*----------------------------------------------------------------------------
     ; Function body here
diff --git a/media/libstagefright/codecs/amrnb/common/src/norm_s.cpp b/media/libstagefright/codecs/amrnb/common/src/norm_s.cpp
index 8cdcdb8..6468b67 100644
--- a/media/libstagefright/codecs/amrnb/common/src/norm_s.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/norm_s.cpp
@@ -194,13 +194,13 @@
 ----------------------------------------------------------------------------*/
 #if !( defined(PV_ARM_V5) || defined(PV_ARM_GCC_V5) )
 
-Word16 norm_s(register Word16 var1)
+Word16 norm_s(Word16 var1)
 {
     /*----------------------------------------------------------------------------
     ; Define all local variables
     ----------------------------------------------------------------------------*/
 
-    register Word16 var_out = 0;
+    Word16 var_out = 0;
 
     /*----------------------------------------------------------------------------
     ; Function body here
diff --git a/media/libstagefright/codecs/amrnb/common/src/pred_lt.cpp b/media/libstagefright/codecs/amrnb/common/src/pred_lt.cpp
index 9163623..8a1aa9e 100644
--- a/media/libstagefright/codecs/amrnb/common/src/pred_lt.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/pred_lt.cpp
@@ -260,9 +260,9 @@
     Flag  *pOverflow  /* output: if set, overflow occurred in this function */
 )
 {
-    register Word16 i;
-    register Word16 j;
-    register Word16 k;
+    Word16 i;
+    Word16 j;
+    Word16 k;
 
     Word16 *pX0;
     Word16 *pX2;
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf_3.cpp b/media/libstagefright/codecs/amrnb/common/src/q_plsf_3.cpp
index 2b30bf4..c70847e 100644
--- a/media/libstagefright/codecs/amrnb/common/src/q_plsf_3.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/q_plsf_3.cpp
@@ -281,7 +281,7 @@
     Flag  *pOverflow      /* o : Flag set when overflow occurs     */
 )
 {
-    register Word16 i;
+    Word16 i;
     Word16 temp;
     const Word16 *p_dico;
     Word16 index = 0;
@@ -607,7 +607,7 @@
     Flag use_half,        /* i: use every second entry in codebook */
     Flag  *pOverflow)     /* o : Flag set when overflow occurs     */
 {
-    register Word16 i;
+    Word16 i;
     Word16 temp;
 
     const Word16 *p_dico;
@@ -1013,7 +1013,7 @@
     Flag  *pOverflow    /* o : Flag set when overflow occurs             */
 )
 {
-    register Word16 i, j;
+    Word16 i, j;
     Word16 lsf1[M];
     Word16 wf1[M];
     Word16 lsf_p[M];
diff --git a/media/libstagefright/codecs/amrnb/common/src/residu.cpp b/media/libstagefright/codecs/amrnb/common/src/residu.cpp
index b25d3be..2ad132f 100644
--- a/media/libstagefright/codecs/amrnb/common/src/residu.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/residu.cpp
@@ -202,7 +202,7 @@
 {
 
 
-    register Word16 i, j;
+    Word16 i, j;
     Word32 s1;
     Word32 s2;
     Word32 s3;
diff --git a/media/libstagefright/codecs/amrnb/common/src/shr.cpp b/media/libstagefright/codecs/amrnb/common/src/shr.cpp
index 775dc69..1018d9c 100644
--- a/media/libstagefright/codecs/amrnb/common/src/shr.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/shr.cpp
@@ -202,10 +202,10 @@
 /*----------------------------------------------------------------------------
 ; FUNCTION CODE
 ----------------------------------------------------------------------------*/
-Word16 shr(register Word16 var1, register Word16 var2, Flag *pOverflow)
+Word16 shr(Word16 var1, Word16 var2, Flag *pOverflow)
 {
-    register Word16 result;
-    register Word32 temp_res;
+    Word16 result;
+    Word32 temp_res;
 
     if (var2 != 0)
     {
diff --git a/media/libstagefright/codecs/amrnb/common/src/weight_a.cpp b/media/libstagefright/codecs/amrnb/common/src/weight_a.cpp
index 2e2efc4..ee821ef 100644
--- a/media/libstagefright/codecs/amrnb/common/src/weight_a.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/weight_a.cpp
@@ -178,7 +178,7 @@
     Word16 a_exp[]      /* (o)   : Spectral expanded LPC coefficients   */
 )
 {
-    register Word16 i;
+    Word16 i;
 
     *(a_exp) = *(a);
 
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index 4aa8c17..3750e2e 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -45,7 +45,7 @@
         $(LOCAL_PATH)/../common/include
 
 LOCAL_CFLAGS := \
-        -DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF=
+        -D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_IMPORT_REF=
 
 LOCAL_CFLAGS += -Werror
 
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d1035pf.cpp b/media/libstagefright/codecs/amrnb/dec/src/d1035pf.cpp
index 899daba..861b3e6 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/d1035pf.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/src/d1035pf.cpp
@@ -209,7 +209,7 @@
     Word16 cod[]       /* (o)     : algebraic (fixed) codebook excitation    */
 )
 {
-    register Word16 i, j, pos1, pos2;
+    Word16 i, j, pos1, pos2;
     Word16 sign, tmp;
 
     for (i = 0; i < L_CODE; i++)
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_plsf_5.cpp b/media/libstagefright/codecs/amrnb/dec/src/d_plsf_5.cpp
index 08b690d..7068c0a 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/d_plsf_5.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/src/d_plsf_5.cpp
@@ -308,7 +308,7 @@
     Flag  *pOverflow    /* o : Flag set when overflow occurs                */
 )
 {
-    register Word16 i;
+    Word16 i;
     Word16 temp;
     Word16 sign;
 
diff --git a/media/libstagefright/codecs/amrnb/dec/src/int_lsf.cpp b/media/libstagefright/codecs/amrnb/dec/src/int_lsf.cpp
index c5aefe4..2ca30de 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/int_lsf.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/src/int_lsf.cpp
@@ -218,9 +218,9 @@
     Flag  *pOverflow  /* o : flag set if overflow occurs                    */
 )
 {
-    register Word16 i;
-    register Word16 temp1;
-    register Word16 temp2;
+    Word16 i;
+    Word16 temp1;
+    Word16 temp2;
 
     if (i_subfr == 0)
     {
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ph_disp.cpp b/media/libstagefright/codecs/amrnb/dec/src/ph_disp.cpp
index da5445b..285465f 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/ph_disp.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/src/ph_disp.cpp
@@ -207,7 +207,7 @@
 
 Word16 ph_disp_reset(ph_dispState *state)
 {
-    register Word16 i;
+    Word16 i;
 
     if (state == (ph_dispState *) NULL)
     {
@@ -667,15 +667,15 @@
     Flag   *pOverflow       /* i/o     : oveflow indicator                  */
 )
 {
-    register Word16 i, i1;
-    register Word16 tmp1;
+    Word16 i, i1;
+    Word16 tmp1;
     Word32 L_temp;
     Word32 L_temp2;
     Word16 impNr;           /* indicator for amount of disp./filter used */
 
     Word16 inno_sav[L_SUBFR];
     Word16 ps_poss[L_SUBFR];
-    register Word16 nze, nPulse;
+    Word16 nze, nPulse;
     Word16 ppos;
     const Word16 *ph_imp;   /* Pointer to phase dispersion filter */
 
diff --git a/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp b/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp
index 0336990..39e01a2 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp
@@ -445,13 +445,13 @@
 )
 {
     Word16 Ap3[MP1];
-    Word16 Ap4[MP1];            /* bandwidth expanded LP parameters */
-    Word16 *Az;                 /* pointer to Az_4:                 */
+    Word16 Ap4[MP1];      /* bandwidth expanded LP parameters */
+    Word16 *Az;           /* pointer to Az_4:                 */
     /*  LPC parameters in each subframe */
-    register Word16 i_subfr;    /* index for beginning of subframe  */
+    Word16 i_subfr;       /* index for beginning of subframe  */
     Word16 h[L_H];
 
-    register Word16 i;
+    Word16 i;
     Word16 temp1;
     Word16 temp2;
     Word32 L_tmp;
diff --git a/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp b/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp
old mode 100755
new mode 100644
index 521fe2b..41a9e98
--- a/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp
@@ -26,6 +26,7 @@
  * SUCH DAMAGE.
  */
 
+#include <malloc.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <string.h>
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.mk b/media/libstagefright/codecs/amrnb/enc/Android.mk
index afc0b89..bdba8a9 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.mk
+++ b/media/libstagefright/codecs/amrnb/enc/Android.mk
@@ -67,7 +67,7 @@
         $(LOCAL_PATH)/../common/include
 
 LOCAL_CFLAGS := \
-        -DOSCL_UNUSED_ARG=
+        -D"OSCL_UNUSED_ARG(x)=(void)(x)"
 
 LOCAL_CFLAGS += -Werror
 
diff --git a/media/libstagefright/codecs/amrnb/enc/src/autocorr.cpp b/media/libstagefright/codecs/amrnb/enc/src/autocorr.cpp
index 0d3acac..c71811d 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/autocorr.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/autocorr.cpp
@@ -306,9 +306,9 @@
     Flag  *pOverflow       /* (o)    : indicates overflow                 */
 )
 {
-    register Word16 i;
-    register Word16 j;
-    register Word16 norm;
+    Word16 i;
+    Word16 j;
+    Word16 norm;
 
     Word16 y[L_WINDOW];
     Word32 sum;
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.cpp b/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.cpp
index a33cdf74..b211032 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.cpp
@@ -318,7 +318,7 @@
         Word16 dn_sign[L_CODE];
         Word16 rr[L_CODE][L_CODE];
 
-        register Word16 i;
+        Word16 i;
 
         Word16 index;
         Word16 sharp;
@@ -592,10 +592,10 @@
         Flag   * pOverflow   /* o : Flag set when overflow occurs      */
     )
     {
-        register Word16 i0;
-        register Word16 i1;
+        Word16 i0;
+        Word16 i1;
         Word16 ix = 0; /* initialization only needed to keep gcc silent */
-        register Word16  track1;
+        Word16 track1;
         Word16 ipos[NB_PULSE];
         Word16 psk;
         Word16 ps0;
@@ -608,7 +608,7 @@
         Word32 s;
         Word32 alp0;
         Word32 alp1;
-        register Word16 i;
+        Word16 i;
         Word32 L_temp;
         Word16 *p_codvec = &codvec[0];
 
@@ -993,13 +993,13 @@
         Flag  *pOverflow  /* o : Flag set when overflow occurs              */
     )
     {
-        register Word16 i;
-        register Word16 j;
-        register Word16 k;
-        register Word16 track;
-        register Word16 first;
-        register Word16 index;
-        register Word16 rsign;
+        Word16 i;
+        Word16 j;
+        Word16 k;
+        Word16 track;
+        Word16 first;
+        Word16 index;
+        Word16 rsign;
         Word16 indx;
         Word16 _sign[NB_PULSE];
         Word16 *p0;
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.cpp b/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.cpp
index 4a05327..525e57d 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.cpp
@@ -638,7 +638,7 @@
     Flag   *pOverflow    /* o   : overflow indicator                        */
 )
 {
-    register Word16 i;
+    Word16 i;
     Word16 index;
     Word32 L_temp;     /* temporarily variable */
     Word16 resu3;      /* flag for upsample resolution */
diff --git a/media/libstagefright/codecs/amrnb/enc/src/convolve.cpp b/media/libstagefright/codecs/amrnb/enc/src/convolve.cpp
index e9ce7ba..5015a4a 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/convolve.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/convolve.cpp
@@ -212,7 +212,7 @@
     Word16 L           /* (i)     : vector size                            */
 )
 {
-    register Word16 i, n;
+    Word16 i, n;
     Word32 s1, s2;
 
 
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h.cpp b/media/libstagefright/codecs/amrnb/enc/src/cor_h.cpp
index e46d99f..20583c4 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/cor_h.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/cor_h.cpp
@@ -272,8 +272,8 @@
     Flag  *pOverflow
 )
 {
-    register Word16 i;
-    register Word16 dec;
+    Word16 i;
+    Word16 dec;
 
     Word16 h2[L_CODE];
     Word32 s;
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.cpp b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.cpp
index beb2aec..c25c026 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.cpp
@@ -249,9 +249,9 @@
     Flag   *pOverflow /* (o): pointer to overflow flag                      */
 )
 {
-    register Word16 i;
-    register Word16 j;
-    register Word16 k;
+    Word16 i;
+    Word16 j;
+    Word16 k;
 
     Word32 s;
     Word32 y32[L_CODE];
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp
index da60640..b4fd867 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp
@@ -236,9 +236,9 @@
     Flag *pOverflow
 )
 {
-    register Word16 i;
-    register Word16 j;
-    register Word16 k;
+    Word16 i;
+    Word16 j;
+    Word16 k;
     Word32 s;
     Word32 y32[L_CODE];
     Word32 max;
diff --git a/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.cpp b/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.cpp
index 276e590..2ccb777 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.cpp
@@ -130,7 +130,7 @@
 ; MACROS
 ; Define module specific macros here
 ----------------------------------------------------------------------------*/
-extern Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow);
+extern Word32 L_add(Word32 L_var1, Word32 L_var2, Flag *pOverflow);
 
 /*----------------------------------------------------------------------------
 ; DEFINES
@@ -671,7 +671,7 @@
              Flag   *pOverflow        /* i/o : overflow indicator            */
             )
 {
-    register Word16 i, j;
+    Word16 i, j;
     Word16 temp;
     Word16 log_en;
     Word16 lsf[M];
@@ -943,7 +943,7 @@
                )
 {
 
-    register Word16 i;
+    Word16 i;
     Word32 L_frame_en;
     Word32 L_temp;
     Word16 log_en_e;
diff --git a/media/libstagefright/codecs/amrnb/enc/src/levinson.cpp b/media/libstagefright/codecs/amrnb/enc/src/levinson.cpp
index 001897b..29cdac6 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/levinson.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/levinson.cpp
@@ -638,8 +638,8 @@
     Flag   *pOverflow
 )
 {
-    register Word16 i;
-    register Word16 j;
+    Word16 i;
+    Word16 j;
     Word16 hi;
     Word16 lo;
     Word16 Kh;                    /* reflexion coefficient; hi and lo   */
@@ -651,9 +651,9 @@
     Word16 Al[M + 1];
     Word16 Anh[M + 1];            /* LPC coef.for next iteration in     */
     Word16 Anl[M + 1];            /* double prec.                       */
-    register Word32 t0;           /* temporary variable                 */
-    register Word32 t1;           /* temporary variable                 */
-    register Word32 t2;           /* temporary variable                 */
+    Word32 t0;                    /* temporary variable                 */
+    Word32 t1;                    /* temporary variable                 */
+    Word32 t2;                    /* temporary variable                 */
 
     Word16 *p_Rh;
     Word16 *p_Rl;
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.cpp b/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.cpp
index d3a2ec0..c039bb0 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.cpp
@@ -320,7 +320,7 @@
 )
 #endif
 {
-    register Word16 i;
+    Word16 i;
     Word16 *p;
     Word32 max;
     Word32 t0;
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pre_proc.cpp b/media/libstagefright/codecs/amrnb/enc/src/pre_proc.cpp
index fdc2440..042920e 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/pre_proc.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/pre_proc.cpp
@@ -542,7 +542,7 @@
     Word16 signal[], /* input/output signal */
     Word16 lg)       /* length of signal    */
 {
-    register Word16 i;
+    Word16 i;
     Word16 x_n_2;
     Word16 x_n_1;
     Word32 L_tmp;
diff --git a/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp b/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp
index d626de3..fa43f78 100644
--- a/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp
@@ -248,7 +248,7 @@
               Word16 n       /* i   : # of maximum correlations in dn2[]    */
              )
 {
-    register Word16 i, j, k;
+    Word16 i, j, k;
     Word16 val, min;
     Word16 pos = 0; /* initialization only needed to keep gcc silent */
 
diff --git a/media/libstagefright/codecs/amrwb/Android.mk b/media/libstagefright/codecs/amrwb/Android.mk
index efdf988..686f7a3 100644
--- a/media/libstagefright/codecs/amrwb/Android.mk
+++ b/media/libstagefright/codecs/amrwb/Android.mk
@@ -48,7 +48,7 @@
         $(LOCAL_PATH)/include
 
 LOCAL_CFLAGS := \
-        -DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF=
+        -D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_IMPORT_REF=
 
 LOCAL_CFLAGS += -Werror
 
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.cpp b/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.cpp
index d1ec790..5872512 100644
--- a/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.cpp
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.cpp
@@ -205,7 +205,7 @@
 {
 
     int16 var_out = 0;
-    register int16 iteration;
+    int16 iteration;
     int32 L_num;
     int32 L_denom;
     int32 L_denom_by_2;
diff --git a/media/libstagefright/codecs/amrwbenc/src/q_pulse.c b/media/libstagefright/codecs/amrwbenc/src/q_pulse.c
index 80a0b73..d658602 100644
--- a/media/libstagefright/codecs/amrwbenc/src/q_pulse.c
+++ b/media/libstagefright/codecs/amrwbenc/src/q_pulse.c
@@ -188,7 +188,7 @@
 		Word16 pos[],                         /* (i) position of the pulse 1..4  */
 		Word16 N)                             /* (i) number of bits for position */
 {
-	Word16 nb_pos, mask, n_1, tmp;
+	Word16 nb_pos, mask __unused, n_1, tmp;
 	Word16 posA[4], posB[4];
 	Word32 i, j, k, index;
 
diff --git a/media/libstagefright/codecs/amrwbenc/src/wb_vad.c b/media/libstagefright/codecs/amrwbenc/src/wb_vad.c
index 13dd2aa..2beaefd 100644
--- a/media/libstagefright/codecs/amrwbenc/src/wb_vad.c
+++ b/media/libstagefright/codecs/amrwbenc/src/wb_vad.c
@@ -404,7 +404,7 @@
 		alpha_down = ALPHA_DOWN1;
 	} else
 	{
-		if ((st->stat_count == 0))
+		if (st->stat_count == 0)
 		{
 			alpha_up = ALPHA_UP2;
 			alpha_down = ALPHA_DOWN2;
diff --git a/media/libstagefright/codecs/avc/common/src/deblock.cpp b/media/libstagefright/codecs/avc/common/src/deblock.cpp
index de2d2b6..5f8b693 100644
--- a/media/libstagefright/codecs/avc/common/src/deblock.cpp
+++ b/media/libstagefright/codecs/avc/common/src/deblock.cpp
@@ -1279,7 +1279,7 @@
     int  C0, c0, dif, AbsDelta, Strng, tmp, tmp1;
     int  L2 = 0, L1, L0, R0, R1, R2 = 0;
     uint8 *ptr, *ptr1;
-    register uint R_in, L_in;
+    uint R_in, L_in;
     uint R_out, L_out;
 
 
diff --git a/media/libstagefright/codecs/avc/enc/Android.mk b/media/libstagefright/codecs/avc/enc/Android.mk
index 537ba42..2ceebc8 100644
--- a/media/libstagefright/codecs/avc/enc/Android.mk
+++ b/media/libstagefright/codecs/avc/enc/Android.mk
@@ -28,7 +28,7 @@
     $(TOP)/frameworks/native/include/media/openmax
 
 LOCAL_CFLAGS := \
-    -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
+    -DOSCL_IMPORT_REF= -D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_EXPORT_REF=
 
 LOCAL_CFLAGS += -Werror
 
@@ -51,7 +51,7 @@
         $(LOCAL_PATH)/../common
 
 LOCAL_CFLAGS := \
-    -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
+    -DOSCL_IMPORT_REF= -D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_EXPORT_REF=
 
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
index cfc37b7..928a74f 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp
@@ -17,6 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "SoftAVCEncoder"
 #include <utils/Log.h>
+#include <utils/misc.h>
 
 #include "avcenc_api.h"
 #include "avcenc_int.h"
@@ -25,6 +26,7 @@
 #include <HardwareAPI.h>
 #include <MetadataBufferType.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
@@ -51,31 +53,36 @@
     params->nVersion.s.nStep = 0;
 }
 
+static const CodecProfileLevel kProfileLevels[] = {
+    { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2  },
+};
+
 typedef struct LevelConversion {
     OMX_U32 omxLevel;
     AVCLevel avcLevel;
+    uint32_t maxMacroBlocks;
 } LevelConcersion;
 
 static LevelConversion ConversionTable[] = {
-    { OMX_VIDEO_AVCLevel1,  AVC_LEVEL1_B },
-    { OMX_VIDEO_AVCLevel1b, AVC_LEVEL1   },
-    { OMX_VIDEO_AVCLevel11, AVC_LEVEL1_1 },
-    { OMX_VIDEO_AVCLevel12, AVC_LEVEL1_2 },
-    { OMX_VIDEO_AVCLevel13, AVC_LEVEL1_3 },
-    { OMX_VIDEO_AVCLevel2,  AVC_LEVEL2 },
+    { OMX_VIDEO_AVCLevel1,  AVC_LEVEL1_B, 99 },
+    { OMX_VIDEO_AVCLevel1b, AVC_LEVEL1,   99 },
+    { OMX_VIDEO_AVCLevel11, AVC_LEVEL1_1, 396 },
+    { OMX_VIDEO_AVCLevel12, AVC_LEVEL1_2, 396 },
+    { OMX_VIDEO_AVCLevel13, AVC_LEVEL1_3, 396 },
+    { OMX_VIDEO_AVCLevel2,  AVC_LEVEL2,   396 },
 #if 0
-    // encoding speed is very poor if video
-    // resolution is higher than CIF
-    { OMX_VIDEO_AVCLevel21, AVC_LEVEL2_1 },
-    { OMX_VIDEO_AVCLevel22, AVC_LEVEL2_2 },
-    { OMX_VIDEO_AVCLevel3,  AVC_LEVEL3   },
-    { OMX_VIDEO_AVCLevel31, AVC_LEVEL3_1 },
-    { OMX_VIDEO_AVCLevel32, AVC_LEVEL3_2 },
-    { OMX_VIDEO_AVCLevel4,  AVC_LEVEL4   },
-    { OMX_VIDEO_AVCLevel41, AVC_LEVEL4_1 },
-    { OMX_VIDEO_AVCLevel42, AVC_LEVEL4_2 },
-    { OMX_VIDEO_AVCLevel5,  AVC_LEVEL5   },
-    { OMX_VIDEO_AVCLevel51, AVC_LEVEL5_1 },
+    // encoding speed is very poor if video resolution
+    // is higher than CIF or if level is higher than 2
+    { OMX_VIDEO_AVCLevel21, AVC_LEVEL2_1, 792 },
+    { OMX_VIDEO_AVCLevel22, AVC_LEVEL2_2, 1620 },
+    { OMX_VIDEO_AVCLevel3,  AVC_LEVEL3,   1620 },
+    { OMX_VIDEO_AVCLevel31, AVC_LEVEL3_1, 3600 },
+    { OMX_VIDEO_AVCLevel32, AVC_LEVEL3_2, 5120 },
+    { OMX_VIDEO_AVCLevel4,  AVC_LEVEL4,   8192 },
+    { OMX_VIDEO_AVCLevel41, AVC_LEVEL4_1, 8192 },
+    { OMX_VIDEO_AVCLevel42, AVC_LEVEL4_2, 8704 },
+    { OMX_VIDEO_AVCLevel5,  AVC_LEVEL5,   22080 },
+    { OMX_VIDEO_AVCLevel51, AVC_LEVEL5_1, 36864 },
 #endif
 };
 
@@ -148,13 +155,11 @@
             const OMX_CALLBACKTYPE *callbacks,
             OMX_PTR appData,
             OMX_COMPONENTTYPE **component)
-    : SoftVideoEncoderOMXComponent(name, callbacks, appData, component),
-      mVideoWidth(176),
-      mVideoHeight(144),
-      mVideoFrameRate(30),
-      mVideoBitRate(192000),
-      mVideoColorFormat(OMX_COLOR_FormatYUV420Planar),
-      mStoreMetaDataInBuffers(false),
+    : SoftVideoEncoderOMXComponent(
+            name, "video_encoder.avc", OMX_VIDEO_CodingAVC,
+            kProfileLevels, NELEM(kProfileLevels),
+            176 /* width */, 144 /* height */,
+            callbacks, appData, component),
       mIDRFrameRefreshIntervalInSec(1),
       mAVCEncProfile(AVC_BASELINE),
       mAVCEncLevel(AVC_LEVEL2),
@@ -168,7 +173,13 @@
       mInputFrameData(NULL),
       mSliceGroup(NULL) {
 
-    initPorts();
+    const size_t kOutputBufferSize =
+        320 * ConversionTable[NELEM(ConversionTable) - 1].maxMacroBlocks;
+
+    initPorts(
+            kNumBuffers, kNumBuffers, kOutputBufferSize,
+            MEDIA_MIMETYPE_VIDEO_AVC, 2 /* minCompressionRatio */);
+
     ALOGI("Construct SoftAVCEncoder");
 }
 
@@ -230,30 +241,28 @@
 
     mEncParams->use_overrun_buffer = AVC_OFF;
 
-    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar
-            || mStoreMetaDataInBuffers) {
+    if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
         // Color conversion is needed.
         free(mInputFrameData);
         mInputFrameData =
-            (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+            (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1);
         CHECK(mInputFrameData != NULL);
     }
 
     // PV's AVC encoder requires the video dimension of multiple
-    if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+    if (mWidth % 16 != 0 || mHeight % 16 != 0) {
         ALOGE("Video frame size %dx%d must be a multiple of 16",
-            mVideoWidth, mVideoHeight);
+            mWidth, mHeight);
         return OMX_ErrorBadParameter;
     }
 
-    mEncParams->width = mVideoWidth;
-    mEncParams->height = mVideoHeight;
-    mEncParams->bitrate = mVideoBitRate;
-    mEncParams->frame_rate = 1000 * mVideoFrameRate;  // In frames/ms!
-    mEncParams->CPB_size = (uint32_t) (mVideoBitRate >> 1);
+    mEncParams->width = mWidth;
+    mEncParams->height = mHeight;
+    mEncParams->bitrate = mBitrate;
+    mEncParams->frame_rate = (1000 * mFramerate) >> 16;  // In frames/ms!, mFramerate is in Q16
+    mEncParams->CPB_size = (uint32_t) (mBitrate >> 1);
 
-    int32_t nMacroBlocks = ((((mVideoWidth + 15) >> 4) << 4) *
-            (((mVideoHeight + 15) >> 4) << 4)) >> 8;
+    int32_t nMacroBlocks = divUp(mWidth, 16) * divUp(mHeight, 16);
     CHECK(mSliceGroup == NULL);
     mSliceGroup = (uint32_t *) malloc(sizeof(uint32_t) * nMacroBlocks);
     CHECK(mSliceGroup != NULL);
@@ -272,7 +281,7 @@
         mEncParams->idr_period = 1;  // All I frames
     } else {
         mEncParams->idr_period =
-            (mIDRFrameRefreshIntervalInSec * mVideoFrameRate);
+            (mIDRFrameRefreshIntervalInSec * mFramerate) >> 16; // mFramerate is in Q16
     }
 
     // Set profile and level
@@ -345,71 +354,9 @@
     mOutputBuffers.clear();
 }
 
-void SoftAVCEncoder::initPorts() {
-    OMX_PARAM_PORTDEFINITIONTYPE def;
-    InitOMXParams(&def);
-
-    const size_t kInputBufferSize = (mVideoWidth * mVideoHeight * 3) >> 1;
-
-    // 31584 is PV's magic number.  Not sure why.
-    const size_t kOutputBufferSize =
-            (kInputBufferSize > 31584) ? kInputBufferSize: 31584;
-
-    def.nPortIndex = 0;
-    def.eDir = OMX_DirInput;
-    def.nBufferCountMin = kNumBuffers;
-    def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kInputBufferSize;
-    def.bEnabled = OMX_TRUE;
-    def.bPopulated = OMX_FALSE;
-    def.eDomain = OMX_PortDomainVideo;
-    def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 1;
-
-    def.format.video.cMIMEType = const_cast<char *>("video/raw");
-    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
-    def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
-    def.format.video.xFramerate = (mVideoFrameRate << 16);  // Q16 format
-    def.format.video.nBitrate = mVideoBitRate;
-    def.format.video.nFrameWidth = mVideoWidth;
-    def.format.video.nFrameHeight = mVideoHeight;
-    def.format.video.nStride = mVideoWidth;
-    def.format.video.nSliceHeight = mVideoHeight;
-
-    addPort(def);
-
-    def.nPortIndex = 1;
-    def.eDir = OMX_DirOutput;
-    def.nBufferCountMin = kNumBuffers;
-    def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kOutputBufferSize;
-    def.bEnabled = OMX_TRUE;
-    def.bPopulated = OMX_FALSE;
-    def.eDomain = OMX_PortDomainVideo;
-    def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 2;
-
-    def.format.video.cMIMEType = const_cast<char *>("video/avc");
-    def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
-    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
-    def.format.video.xFramerate = (0 << 16);  // Q16 format
-    def.format.video.nBitrate = mVideoBitRate;
-    def.format.video.nFrameWidth = mVideoWidth;
-    def.format.video.nFrameHeight = mVideoHeight;
-    def.format.video.nStride = mVideoWidth;
-    def.format.video.nSliceHeight = mVideoHeight;
-
-    addPort(def);
-}
-
 OMX_ERRORTYPE SoftAVCEncoder::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch (index) {
-        case OMX_IndexParamVideoErrorCorrection:
-        {
-            return OMX_ErrorNotImplemented;
-        }
-
         case OMX_IndexParamVideoBitrate:
         {
             OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -420,37 +367,7 @@
             }
 
             bitRate->eControlRate = OMX_Video_ControlRateVariable;
-            bitRate->nTargetBitrate = mVideoBitRate;
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-        {
-            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
-            if (formatParams->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (formatParams->nIndex > 2) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (formatParams->nPortIndex == 0) {
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
-                if (formatParams->nIndex == 0) {
-                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
-                } else if (formatParams->nIndex == 1) {
-                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
-                } else {
-                    formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
-                }
-            } else {
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
-                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
-            }
-
+            bitRate->nTargetBitrate = mBitrate;
             return OMX_ErrorNone;
         }
 
@@ -487,30 +404,8 @@
             return OMX_ErrorNone;
         }
 
-        case OMX_IndexParamVideoProfileLevelQuerySupported:
-        {
-            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
-                (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)params;
-
-            if (profileLevel->nPortIndex != 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            const size_t size =
-                    sizeof(ConversionTable) / sizeof(ConversionTable[0]);
-
-            if (profileLevel->nProfileIndex >= size) {
-                return OMX_ErrorNoMore;
-            }
-
-            profileLevel->eProfile = OMX_VIDEO_AVCProfileBaseline;
-            profileLevel->eLevel = ConversionTable[profileLevel->nProfileIndex].omxLevel;
-
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalGetParameter(index, params);
+            return SoftVideoEncoderOMXComponent::internalGetParameter(index, params);
     }
 }
 
@@ -519,11 +414,6 @@
     int32_t indexFull = index;
 
     switch (indexFull) {
-        case OMX_IndexParamVideoErrorCorrection:
-        {
-            return OMX_ErrorNotImplemented;
-        }
-
         case OMX_IndexParamVideoBitrate:
         {
             OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -534,109 +424,7 @@
                 return OMX_ErrorUndefined;
             }
 
-            mVideoBitRate = bitRate->nTargetBitrate;
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamPortDefinition:
-        {
-            OMX_PARAM_PORTDEFINITIONTYPE *def =
-                (OMX_PARAM_PORTDEFINITIONTYPE *)params;
-            if (def->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (def->nPortIndex == 0) {
-                if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused ||
-                    (def->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar &&
-                     def->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
-                     def->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
-                    return OMX_ErrorUndefined;
-                }
-            } else {
-                if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingAVC ||
-                    (def->format.video.eColorFormat != OMX_COLOR_FormatUnused)) {
-                    return OMX_ErrorUndefined;
-                }
-            }
-
-            OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter(index, params);
-            if (OMX_ErrorNone != err) {
-                return err;
-            }
-
-            if (def->nPortIndex == 0) {
-                mVideoWidth = def->format.video.nFrameWidth;
-                mVideoHeight = def->format.video.nFrameHeight;
-                mVideoFrameRate = def->format.video.xFramerate >> 16;
-                mVideoColorFormat = def->format.video.eColorFormat;
-
-                OMX_PARAM_PORTDEFINITIONTYPE *portDef =
-                    &editPortInfo(0)->mDef;
-                portDef->format.video.nFrameWidth = mVideoWidth;
-                portDef->format.video.nFrameHeight = mVideoHeight;
-                portDef->format.video.nStride = portDef->format.video.nFrameWidth;
-                portDef->format.video.nSliceHeight = portDef->format.video.nFrameHeight;
-                portDef->format.video.xFramerate = def->format.video.xFramerate;
-                portDef->format.video.eColorFormat =
-                    (OMX_COLOR_FORMATTYPE) mVideoColorFormat;
-                portDef->nBufferSize =
-                    (portDef->format.video.nStride * portDef->format.video.nSliceHeight * 3) / 2;
-                portDef = &editPortInfo(1)->mDef;
-                portDef->format.video.nFrameWidth = mVideoWidth;
-                portDef->format.video.nFrameHeight = mVideoHeight;
-            } else {
-                mVideoBitRate = def->format.video.nBitrate;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamStandardComponentRole:
-        {
-            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
-                (const OMX_PARAM_COMPONENTROLETYPE *)params;
-
-            if (strncmp((const char *)roleParams->cRole,
-                        "video_encoder.avc",
-                        OMX_MAX_STRINGNAME_SIZE - 1)) {
-                return OMX_ErrorUndefined;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-        {
-            const OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
-            if (formatParams->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (formatParams->nIndex > 2) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (formatParams->nPortIndex == 0) {
-                if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused ||
-                    ((formatParams->nIndex == 0 &&
-                      formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) ||
-                    (formatParams->nIndex == 1 &&
-                     formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) ||
-                    (formatParams->nIndex == 2 &&
-                     formatParams->eColorFormat != OMX_COLOR_FormatAndroidOpaque) )) {
-                    return OMX_ErrorUndefined;
-                }
-                mVideoColorFormat = formatParams->eColorFormat;
-            } else {
-                if (formatParams->eCompressionFormat != OMX_VIDEO_CodingAVC ||
-                    formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
-                    return OMX_ErrorUndefined;
-                }
-            }
-
+            mBitrate = bitRate->nTargetBitrate;
             return OMX_ErrorNone;
         }
 
@@ -673,29 +461,8 @@
             return OMX_ErrorNone;
         }
 
-        case kStoreMetaDataExtensionIndex:
-        {
-            StoreMetaDataInBuffersParams *storeParams =
-                    (StoreMetaDataInBuffersParams*)params;
-            if (storeParams->nPortIndex != 0) {
-                ALOGE("%s: StoreMetadataInBuffersParams.nPortIndex not zero!",
-                        __FUNCTION__);
-                return OMX_ErrorUndefined;
-            }
-
-            mStoreMetaDataInBuffers = storeParams->bStoreMetaData;
-            ALOGV("StoreMetaDataInBuffers set to: %s",
-                    mStoreMetaDataInBuffers ? " true" : "false");
-
-            if (mStoreMetaDataInBuffers) {
-                mVideoColorFormat = OMX_COLOR_FormatAndroidOpaque;
-            }
-
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalSetParameter(index, params);
+            return SoftVideoEncoderOMXComponent::internalSetParameter(index, params);
     }
 }
 
@@ -789,16 +556,16 @@
             if (inHeader->nFilledLen > 0) {
                 AVCFrameIO videoInput;
                 memset(&videoInput, 0, sizeof(videoInput));
-                videoInput.height = ((mVideoHeight  + 15) >> 4) << 4;
-                videoInput.pitch = ((mVideoWidth + 15) >> 4) << 4;
+                videoInput.height = align(mHeight, 16);
+                videoInput.pitch = align(mWidth, 16);
                 videoInput.coding_timestamp = (inHeader->nTimeStamp + 500) / 1000;  // in ms
                 const uint8_t *inputData = NULL;
-                if (mStoreMetaDataInBuffers) {
+                if (mInputDataIsMeta) {
                     inputData =
                         extractGraphicBuffer(
-                                mInputFrameData, (mVideoWidth * mVideoHeight * 3) >> 1,
+                                mInputFrameData, (mWidth * mHeight * 3) >> 1,
                                 inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen,
-                                mVideoWidth, mVideoHeight);
+                                mWidth, mHeight);
                     if (inputData == NULL) {
                         ALOGE("Unable to extract gralloc buffer in metadata mode");
                         mSignalledError = true;
@@ -808,9 +575,9 @@
                     // TODO: Verify/convert pixel format enum
                 } else {
                     inputData = (const uint8_t *)inHeader->pBuffer + inHeader->nOffset;
-                    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+                    if (mColorFormat != OMX_COLOR_FormatYUV420Planar) {
                         ConvertYUV420SemiPlanarToYUV420Planar(
-                            inputData, mInputFrameData, mVideoWidth, mVideoHeight);
+                            inputData, mInputFrameData, mWidth, mHeight);
                         inputData = mInputFrameData;
                     }
                 }
diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
index 130593f..81de109 100644
--- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
+++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.h
@@ -26,8 +26,6 @@
 
 namespace android {
 
-struct MediaBuffer;
-
 struct SoftAVCEncoder : public MediaBufferObserver,
                         public SoftVideoEncoderOMXComponent {
     SoftAVCEncoder(
@@ -68,12 +66,6 @@
         int32_t mFlags;
     } InputBufferInfo;
 
-    int32_t  mVideoWidth;
-    int32_t  mVideoHeight;
-    int32_t  mVideoFrameRate;
-    int32_t  mVideoBitRate;
-    int32_t  mVideoColorFormat;
-    bool     mStoreMetaDataInBuffers;
     int32_t  mIDRFrameRefreshIntervalInSec;
     AVCProfile mAVCEncProfile;
     AVCLevel   mAVCEncLevel;
@@ -94,7 +86,6 @@
     Vector<MediaBuffer *> mOutputBuffers;
     Vector<InputBufferInfo> mInputBufferInfoVec;
 
-    void initPorts();
     OMX_ERRORTYPE initEncParams();
     OMX_ERRORTYPE initEncoder();
     OMX_ERRORTYPE releaseEncoder();
diff --git a/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp b/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp
index 38a2a15..0b8d9e2 100644
--- a/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp
+++ b/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp
@@ -151,8 +151,7 @@
     uint8 tmp8;
     int32 tmp32;
     int16 tmp_horz[18*22], *dst_16, *src_16;
-    register int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; // temp register
-    int msk;
+    int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; // temp
     int i, j;
 
     /* first copy full-pel to the first array */
@@ -379,7 +378,6 @@
     // one can just use the above code and change the for(i=2 to for(i=18
     for (i = 16; i > 0; i -= 4)
     {
-        msk = 0;
         for (j = 17; j > 0; j--)
         {
             a = *((uint32*)ref); /* load 4 bytes */
diff --git a/media/libstagefright/codecs/avc/enc/src/init.cpp b/media/libstagefright/codecs/avc/enc/src/init.cpp
index c258b57..6e1413a 100644
--- a/media/libstagefright/codecs/avc/enc/src/init.cpp
+++ b/media/libstagefright/codecs/avc/enc/src/init.cpp
@@ -177,10 +177,6 @@
             seqParam->offset_for_non_ref_pic = extS->offset_for_non_ref_pic;
             seqParam->offset_for_top_to_bottom_field = extS->offset_for_top_to_bottom_field;
             seqParam->num_ref_frames_in_pic_order_cnt_cycle = extS->num_ref_frames_in_pic_order_cnt_cycle;
-            if (extS->offset_for_ref_frame == NULL)
-            {
-                return AVCENC_ENCPARAM_MEM_FAIL;
-            }
             for (ii = 0; ii < (int) extS->num_ref_frames; ii++)
             {
                 seqParam->offset_for_ref_frame[ii] = extS->offset_for_ref_frame[ii];
diff --git a/media/libstagefright/codecs/avc/enc/src/rate_control.cpp b/media/libstagefright/codecs/avc/enc/src/rate_control.cpp
index aa13873..09dcc28 100644
--- a/media/libstagefright/codecs/avc/enc/src/rate_control.cpp
+++ b/media/libstagefright/codecs/avc/enc/src/rate_control.cpp
@@ -171,7 +171,7 @@
     AVCRateControl *rateCtrl = encvid->rateCtrl;
     double L1, L2, L3, bpp;
     int qp;
-    int i, j;
+    int i;
 
     rateCtrl->basicUnit = video->PicSizeInMbs;
 
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 1301060..9edffd2 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -421,7 +421,6 @@
     }
 
     FLAC__bool ok = true;
-    FLAC__StreamEncoderInitStatus initStatus = FLAC__STREAM_ENCODER_INIT_STATUS_OK;
     ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mNumChannels);
     ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mSampleRate);
     ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
index 4debc48..bd01a1a 100644
--- a/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
+++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.cpp
@@ -34,6 +34,9 @@
     params->nVersion.s.nStep = 0;
 }
 
+// Microsoft WAV GSM encoding packs two GSM frames into 65 bytes.
+static const int kMSGSMFrameSize = 65;
+
 SoftGSM::SoftGSM(
         const char *name,
         const OMX_CALLBACKTYPE *callbacks,
@@ -64,7 +67,7 @@
     def.eDir = OMX_DirInput;
     def.nBufferCountMin = kNumBuffers;
     def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = sizeof(gsm_frame);
+    def.nBufferSize = 1024 / kMSGSMFrameSize * kMSGSMFrameSize;
     def.bEnabled = OMX_TRUE;
     def.bPopulated = OMX_FALSE;
     def.eDomain = OMX_PortDomainAudio;
@@ -207,8 +210,8 @@
             mSignalledError = true;
         }
 
-        if(((inHeader->nFilledLen / 65) * 65) != inHeader->nFilledLen) {
-            ALOGE("input buffer not multiple of 65 (%d).", inHeader->nFilledLen);
+        if(((inHeader->nFilledLen / kMSGSMFrameSize) * kMSGSMFrameSize) != inHeader->nFilledLen) {
+            ALOGE("input buffer not multiple of %d (%d).", kMSGSMFrameSize, inHeader->nFilledLen);
             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
             mSignalledError = true;
         }
@@ -258,6 +261,25 @@
     return ret;
 }
 
+void SoftGSM::onPortFlushCompleted(OMX_U32 portIndex) {
+    if (portIndex == 0) {
+        gsm_destroy(mGsm);
+        mGsm = gsm_create();
+        int msopt = 1;
+        gsm_option(mGsm, GSM_OPT_WAV49, &msopt);
+    }
+}
+
+void SoftGSM::onReset() {
+    gsm_destroy(mGsm);
+    mGsm = gsm_create();
+    int msopt = 1;
+    gsm_option(mGsm, GSM_OPT_WAV49, &msopt);
+    mSignalledError = false;
+}
+
+
+
 
 }  // namespace android
 
diff --git a/media/libstagefright/codecs/gsm/dec/SoftGSM.h b/media/libstagefright/codecs/gsm/dec/SoftGSM.h
index 8ab6116..0303dea 100644
--- a/media/libstagefright/codecs/gsm/dec/SoftGSM.h
+++ b/media/libstagefright/codecs/gsm/dec/SoftGSM.h
@@ -43,6 +43,9 @@
 
     virtual void onQueueFilled(OMX_U32 portIndex);
 
+    virtual void onPortFlushCompleted(OMX_U32 portIndex);
+    virtual void onReset();
+
 private:
     enum {
         kNumBuffers = 4,
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index f4cba54..cddd176 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -26,6 +26,7 @@
 #include "SoftHEVC.h"
 
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 #include <OMX_VideoExt.h>
 
@@ -75,8 +76,12 @@
       mNewWidth(mWidth),
       mNewHeight(mHeight),
       mChangingResolution(false) {
-    initPorts(kNumBuffers, INPUT_BUF_SIZE, kNumBuffers,
-            CODEC_MIME_TYPE);
+    const size_t kMinCompressionRatio = 4 /* compressionRatio (for Level 4+) */;
+    const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
+    // INPUT_BUF_SIZE is given by HEVC codec as minimum input size
+    initPorts(
+            kNumBuffers, max(kMaxOutputBufferSize / kMinCompressionRatio, (size_t)INPUT_BUF_SIZE),
+            kNumBuffers, CODEC_MIME_TYPE, kMinCompressionRatio);
     CHECK_EQ(initDecoder(), (status_t)OK);
 }
 
@@ -644,7 +649,7 @@
             // The decoder should be fixed so that |u4_error_code| instead of |status| returns
             // IHEVCD_UNSUPPORTED_DIMENSIONS.
             bool unsupportedDimensions =
-                ((IHEVCD_UNSUPPORTED_DIMENSIONS == status)
+                ((IHEVCD_UNSUPPORTED_DIMENSIONS == (IHEVCD_CXA_ERROR_CODES_T)status)
                     || (IHEVCD_UNSUPPORTED_DIMENSIONS == s_dec_op.u4_error_code));
             bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
 
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index e399984..ede645c 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -21,6 +21,7 @@
 #include "SoftMPEG4.h"
 
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/IOMX.h>
@@ -70,7 +71,7 @@
       mPvTime(0) {
     initPorts(
             kNumInputBuffers,
-            8192 /* inputBufferSize */,
+            352 * 288 * 3 / 2 /* minInputBufferSize */,
             kNumOutputBuffers,
             (mMode == MODE_MPEG4)
             ? MEDIA_MIMETYPE_VIDEO_MPEG4 : MEDIA_MIMETYPE_VIDEO_H263);
@@ -353,14 +354,14 @@
     }
 }
 
-void SoftMPEG4::updatePortDefinitions() {
-    SoftVideoDecoderOMXComponent::updatePortDefinitions();
+void SoftMPEG4::updatePortDefinitions(bool updateCrop, bool updateInputSize) {
+    SoftVideoDecoderOMXComponent::updatePortDefinitions(updateCrop, updateInputSize);
 
     /* We have to align our width and height - this should affect stride! */
     OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
-    def->nBufferSize =
-        (((def->format.video.nFrameWidth + 15) & -16)
-            * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2;
+    def->format.video.nStride = align(def->format.video.nStride, 16);
+    def->format.video.nSliceHeight = align(def->format.video.nSliceHeight, 16);
+    def->nBufferSize = (def->format.video.nStride * def->format.video.nSliceHeight * 3) / 2;
 }
 
 }  // namespace android
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
index 8a06a00..4114e7d 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
@@ -66,7 +66,7 @@
 
     status_t initDecoder();
 
-    virtual void updatePortDefinitions();
+    virtual void updatePortDefinitions(bool updateCrop = true, bool updateInputSize = false);
     bool handlePortSettingsChange();
 
     DISALLOW_EVIL_CONSTRUCTORS(SoftMPEG4);
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/find_min_max.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/find_min_max.cpp
index a357ea6..1ac88a1 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/find_min_max.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/find_min_max.cpp
@@ -138,8 +138,8 @@
     /*----------------------------------------------------------------------------
     ; Define all local variables
     ----------------------------------------------------------------------------*/
-    register    uint    i, j;
-    register    int min, max;
+    uint    i, j;
+    int min, max;
 
     /*----------------------------------------------------------------------------
     ; Function body here
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
index 844bd14..90d7c6b 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
@@ -247,10 +247,13 @@
                         video->vol[idx]->useReverseVLC = 0;
                         video->intra_acdcPredDisable = 1;
                         video->vol[idx]->scalability = 0;
-                        video->size = (int32)width * height;
 
-                        video->displayWidth = video->width = width;
-                        video->displayHeight = video->height = height;
+                        video->displayWidth = width;
+                        video->displayHeight = height;
+                        video->width = (width + 15) & -16;
+                        video->height = (height + 15) & -16;
+                        video->size = (int32)video->width * video->height;
+
 #ifdef PV_ANNEX_IJKT_SUPPORT
                         video->modified_quant = 0;
                         video->advanced_INTRA = 0;
@@ -289,8 +292,10 @@
 
     if (video->shortVideoHeader == PV_TRUE)
     {
-        video->displayWidth = video->width = width;
-        video->displayHeight = video->height = height;
+        video->displayWidth = width;
+        video->displayHeight = height;
+        video->width = (width + 15) & -16;
+        video->height = (height + 15) & -16;
 
         video->nMBPerRow =
             video->nMBinGOB  = video->width / MB_SIZE;
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
index b03ec8c..60c79a6 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
@@ -118,6 +118,10 @@
         {
             /* support SPL0-3 & SSPL0-2   */
             if (tmpvar != 0x01 && tmpvar != 0x02 && tmpvar != 0x03 && tmpvar != 0x08 &&
+                    /* While not technically supported, try to decode SPL4&SPL5 files as well. */
+                    /* We'll fail later if the size is too large.  This is to allow playback of */
+                    /* some <=CIF files generated by other encoders. */
+                    tmpvar != 0x04 && tmpvar != 0x05 &&
                     tmpvar != 0x10 && tmpvar != 0x11 && tmpvar != 0x12 &&
                     tmpvar != 0x21 && tmpvar != 0x22 &&  /* Core Profile Levels */
                     tmpvar != 0xA1 && tmpvar != 0xA2 && tmpvar != 0xA3 &&
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.mk b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
index c9006d9..7117692 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.mk
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
@@ -25,7 +25,7 @@
 
 LOCAL_CFLAGS := \
     -DBX_RC \
-    -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
+    -DOSCL_IMPORT_REF= -D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_EXPORT_REF=
 
 LOCAL_C_INCLUDES := \
     $(LOCAL_PATH)/src \
@@ -55,7 +55,7 @@
 
 LOCAL_CFLAGS := \
     -DBX_RC \
-    -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
+    -DOSCL_IMPORT_REF= -D"OSCL_UNUSED_ARG(x)=(void)(x)" -DOSCL_EXPORT_REF=
 
 
 LOCAL_STATIC_LIBRARIES := \
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index 1d0a2f0..8240f83 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -17,6 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "SoftMPEG4Encoder"
 #include <utils/Log.h>
+#include <utils/misc.h>
 
 #include "mp4enc_api.h"
 #include "OMX_Video.h"
@@ -24,6 +25,7 @@
 #include <HardwareAPI.h>
 #include <MetadataBufferType.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
@@ -46,19 +48,30 @@
     params->nVersion.s.nStep = 0;
 }
 
+static const CodecProfileLevel kMPEG4ProfileLevels[] = {
+    { OMX_VIDEO_MPEG4ProfileCore, OMX_VIDEO_MPEG4Level2 },
+};
+
+static const CodecProfileLevel kH263ProfileLevels[] = {
+    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 },
+};
+
 SoftMPEG4Encoder::SoftMPEG4Encoder(
             const char *name,
+            const char *componentRole,
+            OMX_VIDEO_CODINGTYPE codingType,
+            const char *mime,
+            const CodecProfileLevel *profileLevels,
+            size_t numProfileLevels,
             const OMX_CALLBACKTYPE *callbacks,
             OMX_PTR appData,
             OMX_COMPONENTTYPE **component)
-    : SoftVideoEncoderOMXComponent(name, callbacks, appData, component),
+    : SoftVideoEncoderOMXComponent(
+            name, componentRole, codingType,
+            profileLevels, numProfileLevels,
+            176 /* width */, 144 /* height */,
+            callbacks, appData, component),
       mEncodeMode(COMBINE_MODE_WITH_ERR_RES),
-      mVideoWidth(176),
-      mVideoHeight(144),
-      mVideoFrameRate(30),
-      mVideoBitRate(192000),
-      mVideoColorFormat(OMX_COLOR_FormatYUV420Planar),
-      mStoreMetaDataInBuffers(false),
       mIDRFrameRefreshIntervalInSec(1),
       mNumInputFrames(-1),
       mStarted(false),
@@ -68,13 +81,15 @@
       mEncParams(new tagvideoEncOptions),
       mInputFrameData(NULL) {
 
-   if (!strcmp(name, "OMX.google.h263.encoder")) {
+    if (codingType == OMX_VIDEO_CodingH263) {
         mEncodeMode = H263_MODE;
-    } else {
-        CHECK(!strcmp(name, "OMX.google.mpeg4.encoder"));
     }
 
-    initPorts();
+    // 256 * 1024 is a magic number for PV's encoder, not sure why
+    const size_t kOutputBufferSize = 256 * 1024;
+
+    initPorts(kNumBuffers, kNumBuffers, kOutputBufferSize, mime);
+
     ALOGI("Construct SoftMPEG4Encoder");
 }
 
@@ -98,9 +113,9 @@
         return OMX_ErrorUndefined;
     }
     mEncParams->encMode = mEncodeMode;
-    mEncParams->encWidth[0] = mVideoWidth;
-    mEncParams->encHeight[0] = mVideoHeight;
-    mEncParams->encFrameRate[0] = mVideoFrameRate;
+    mEncParams->encWidth[0] = mWidth;
+    mEncParams->encHeight[0] = mHeight;
+    mEncParams->encFrameRate[0] = mFramerate >> 16; // mFramerate is in Q16 format
     mEncParams->rcType = VBR_1;
     mEncParams->vbvDelay = 5.0f;
 
@@ -111,27 +126,26 @@
     mEncParams->rvlcEnable = PV_OFF;
     mEncParams->numLayers = 1;
     mEncParams->timeIncRes = 1000;
-    mEncParams->tickPerSrc = mEncParams->timeIncRes / mVideoFrameRate;
+    mEncParams->tickPerSrc = ((int64_t)mEncParams->timeIncRes << 16) / mFramerate;
 
-    mEncParams->bitRate[0] = mVideoBitRate;
+    mEncParams->bitRate[0] = mBitrate;
     mEncParams->iQuant[0] = 15;
     mEncParams->pQuant[0] = 12;
     mEncParams->quantType[0] = 0;
     mEncParams->noFrameSkipped = PV_OFF;
 
-    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar
-            || mStoreMetaDataInBuffers) {
+    if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
         // Color conversion is needed.
         free(mInputFrameData);
         mInputFrameData =
-            (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+            (uint8_t *) malloc((mWidth * mHeight * 3 ) >> 1);
         CHECK(mInputFrameData != NULL);
     }
 
     // PV's MPEG4 encoder requires the video dimension of multiple
-    if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+    if (mWidth % 16 != 0 || mHeight % 16 != 0) {
         ALOGE("Video frame size %dx%d must be a multiple of 16",
-            mVideoWidth, mVideoHeight);
+            mWidth, mHeight);
         return OMX_ErrorBadParameter;
     }
 
@@ -142,7 +156,7 @@
         mEncParams->intraPeriod = 1;  // All I frames
     } else {
         mEncParams->intraPeriod =
-            (mIDRFrameRefreshIntervalInSec * mVideoFrameRate);
+            (mIDRFrameRefreshIntervalInSec * mFramerate) >> 16;
     }
 
     mEncParams->numIntraMB = 0;
@@ -201,81 +215,9 @@
     return OMX_ErrorNone;
 }
 
-void SoftMPEG4Encoder::initPorts() {
-    OMX_PARAM_PORTDEFINITIONTYPE def;
-    InitOMXParams(&def);
-
-    const size_t kInputBufferSize = (mVideoWidth * mVideoHeight * 3) >> 1;
-
-    // 256 * 1024 is a magic number for PV's encoder, not sure why
-    const size_t kOutputBufferSize =
-        (kInputBufferSize > 256 * 1024)
-            ? kInputBufferSize: 256 * 1024;
-
-    def.nPortIndex = 0;
-    def.eDir = OMX_DirInput;
-    def.nBufferCountMin = kNumBuffers;
-    def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kInputBufferSize;
-    def.bEnabled = OMX_TRUE;
-    def.bPopulated = OMX_FALSE;
-    def.eDomain = OMX_PortDomainVideo;
-    def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 1;
-
-    def.format.video.cMIMEType = const_cast<char *>("video/raw");
-
-    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
-    def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
-    def.format.video.xFramerate = (mVideoFrameRate << 16);  // Q16 format
-    def.format.video.nBitrate = mVideoBitRate;
-    def.format.video.nFrameWidth = mVideoWidth;
-    def.format.video.nFrameHeight = mVideoHeight;
-    def.format.video.nStride = mVideoWidth;
-    def.format.video.nSliceHeight = mVideoHeight;
-
-    addPort(def);
-
-    def.nPortIndex = 1;
-    def.eDir = OMX_DirOutput;
-    def.nBufferCountMin = kNumBuffers;
-    def.nBufferCountActual = def.nBufferCountMin;
-    def.nBufferSize = kOutputBufferSize;
-    def.bEnabled = OMX_TRUE;
-    def.bPopulated = OMX_FALSE;
-    def.eDomain = OMX_PortDomainVideo;
-    def.bBuffersContiguous = OMX_FALSE;
-    def.nBufferAlignment = 2;
-
-    def.format.video.cMIMEType =
-        (mEncodeMode == COMBINE_MODE_WITH_ERR_RES)
-            ? const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG4)
-            : const_cast<char *>(MEDIA_MIMETYPE_VIDEO_H263);
-
-    def.format.video.eCompressionFormat =
-        (mEncodeMode == COMBINE_MODE_WITH_ERR_RES)
-            ? OMX_VIDEO_CodingMPEG4
-            : OMX_VIDEO_CodingH263;
-
-    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
-    def.format.video.xFramerate = (0 << 16);  // Q16 format
-    def.format.video.nBitrate = mVideoBitRate;
-    def.format.video.nFrameWidth = mVideoWidth;
-    def.format.video.nFrameHeight = mVideoHeight;
-    def.format.video.nStride = mVideoWidth;
-    def.format.video.nSliceHeight = mVideoHeight;
-
-    addPort(def);
-}
-
 OMX_ERRORTYPE SoftMPEG4Encoder::internalGetParameter(
         OMX_INDEXTYPE index, OMX_PTR params) {
     switch (index) {
-        case OMX_IndexParamVideoErrorCorrection:
-        {
-            return OMX_ErrorNotImplemented;
-        }
-
         case OMX_IndexParamVideoBitrate:
         {
             OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -286,41 +228,7 @@
             }
 
             bitRate->eControlRate = OMX_Video_ControlRateVariable;
-            bitRate->nTargetBitrate = mVideoBitRate;
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-        {
-            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
-            if (formatParams->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (formatParams->nIndex > 2) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (formatParams->nPortIndex == 0) {
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
-                if (formatParams->nIndex == 0) {
-                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
-                } else if (formatParams->nIndex == 1) {
-                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
-                } else {
-                    formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
-                }
-            } else {
-                formatParams->eCompressionFormat =
-                    (mEncodeMode == COMBINE_MODE_WITH_ERR_RES)
-                        ? OMX_VIDEO_CodingMPEG4
-                        : OMX_VIDEO_CodingH263;
-
-                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
-            }
-
+            bitRate->nTargetBitrate = mBitrate;
             return OMX_ErrorNone;
         }
 
@@ -369,32 +277,8 @@
             return OMX_ErrorNone;
         }
 
-        case OMX_IndexParamVideoProfileLevelQuerySupported:
-        {
-            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
-                (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)params;
-
-            if (profileLevel->nPortIndex != 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (profileLevel->nProfileIndex > 0) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (mEncodeMode == H263_MODE) {
-                profileLevel->eProfile = OMX_VIDEO_H263ProfileBaseline;
-                profileLevel->eLevel = OMX_VIDEO_H263Level45;
-            } else {
-                profileLevel->eProfile = OMX_VIDEO_MPEG4ProfileCore;
-                profileLevel->eLevel = OMX_VIDEO_MPEG4Level2;
-            }
-
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalGetParameter(index, params);
+            return SoftVideoEncoderOMXComponent::internalGetParameter(index, params);
     }
 }
 
@@ -403,11 +287,6 @@
     int32_t indexFull = index;
 
     switch (indexFull) {
-        case OMX_IndexParamVideoErrorCorrection:
-        {
-            return OMX_ErrorNotImplemented;
-        }
-
         case OMX_IndexParamVideoBitrate:
         {
             OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
@@ -418,116 +297,7 @@
                 return OMX_ErrorUndefined;
             }
 
-            mVideoBitRate = bitRate->nTargetBitrate;
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamPortDefinition:
-        {
-            OMX_PARAM_PORTDEFINITIONTYPE *def =
-                (OMX_PARAM_PORTDEFINITIONTYPE *)params;
-            if (def->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (def->nPortIndex == 0) {
-                if (def->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused ||
-                    (def->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar &&
-                     def->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar &&
-                     def->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
-                    return OMX_ErrorUndefined;
-                }
-            } else {
-                if ((mEncodeMode == COMBINE_MODE_WITH_ERR_RES &&
-                        def->format.video.eCompressionFormat != OMX_VIDEO_CodingMPEG4) ||
-                    (mEncodeMode == H263_MODE &&
-                        def->format.video.eCompressionFormat != OMX_VIDEO_CodingH263) ||
-                    (def->format.video.eColorFormat != OMX_COLOR_FormatUnused)) {
-                    return OMX_ErrorUndefined;
-                }
-            }
-
-            OMX_ERRORTYPE err = SimpleSoftOMXComponent::internalSetParameter(index, params);
-            if (OMX_ErrorNone != err) {
-                return err;
-            }
-
-            if (def->nPortIndex == 0) {
-                mVideoWidth = def->format.video.nFrameWidth;
-                mVideoHeight = def->format.video.nFrameHeight;
-                mVideoFrameRate = def->format.video.xFramerate >> 16;
-                mVideoColorFormat = def->format.video.eColorFormat;
-
-                OMX_PARAM_PORTDEFINITIONTYPE *portDef =
-                    &editPortInfo(0)->mDef;
-                portDef->format.video.nFrameWidth = mVideoWidth;
-                portDef->format.video.nFrameHeight = mVideoHeight;
-                portDef->format.video.nStride = portDef->format.video.nFrameWidth;
-                portDef->format.video.nSliceHeight = portDef->format.video.nFrameHeight;
-                portDef->format.video.xFramerate = def->format.video.xFramerate;
-                portDef->format.video.eColorFormat =
-                    (OMX_COLOR_FORMATTYPE) mVideoColorFormat;
-                portDef->nBufferSize =
-                    (portDef->format.video.nStride * portDef->format.video.nSliceHeight * 3) / 2;
-                portDef = &editPortInfo(1)->mDef;
-                portDef->format.video.nFrameWidth = mVideoWidth;
-                portDef->format.video.nFrameHeight = mVideoHeight;
-            } else {
-                mVideoBitRate = def->format.video.nBitrate;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamStandardComponentRole:
-        {
-            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
-                (const OMX_PARAM_COMPONENTROLETYPE *)params;
-
-            if (strncmp((const char *)roleParams->cRole,
-                        (mEncodeMode == H263_MODE)
-                            ? "video_encoder.h263": "video_encoder.mpeg4",
-                        OMX_MAX_STRINGNAME_SIZE - 1)) {
-                return OMX_ErrorUndefined;
-            }
-
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-        {
-            const OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
-
-            if (formatParams->nPortIndex > 1) {
-                return OMX_ErrorUndefined;
-            }
-
-            if (formatParams->nIndex > 2) {
-                return OMX_ErrorNoMore;
-            }
-
-            if (formatParams->nPortIndex == 0) {
-                if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused ||
-                    ((formatParams->nIndex == 0 &&
-                      formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) ||
-                    (formatParams->nIndex == 1 &&
-                     formatParams->eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) ||
-                    (formatParams->nIndex == 2 &&
-                     formatParams->eColorFormat != OMX_COLOR_FormatAndroidOpaque) )) {
-                    return OMX_ErrorUndefined;
-                }
-                mVideoColorFormat = formatParams->eColorFormat;
-            } else {
-                if ((mEncodeMode == H263_MODE &&
-                        formatParams->eCompressionFormat != OMX_VIDEO_CodingH263) ||
-                    (mEncodeMode == COMBINE_MODE_WITH_ERR_RES &&
-                        formatParams->eCompressionFormat != OMX_VIDEO_CodingMPEG4) ||
-                    formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
-                    return OMX_ErrorUndefined;
-                }
-            }
-
+            mBitrate = bitRate->nTargetBitrate;
             return OMX_ErrorNone;
         }
 
@@ -578,29 +348,8 @@
             return OMX_ErrorNone;
         }
 
-        case kStoreMetaDataExtensionIndex:
-        {
-            StoreMetaDataInBuffersParams *storeParams =
-                    (StoreMetaDataInBuffersParams*)params;
-            if (storeParams->nPortIndex != 0) {
-                ALOGE("%s: StoreMetadataInBuffersParams.nPortIndex not zero!",
-                        __FUNCTION__);
-                return OMX_ErrorUndefined;
-            }
-
-            mStoreMetaDataInBuffers = storeParams->bStoreMetaData;
-            ALOGV("StoreMetaDataInBuffers set to: %s",
-                    mStoreMetaDataInBuffers ? " true" : "false");
-
-            if (mStoreMetaDataInBuffers) {
-                mVideoColorFormat = OMX_COLOR_FormatAndroidOpaque;
-            }
-
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalSetParameter(index, params);
+            return SoftVideoEncoderOMXComponent::internalSetParameter(index, params);
     }
 }
 
@@ -663,12 +412,12 @@
 
         if (inHeader->nFilledLen > 0) {
             const uint8_t *inputData = NULL;
-            if (mStoreMetaDataInBuffers) {
+            if (mInputDataIsMeta) {
                 inputData =
                     extractGraphicBuffer(
-                            mInputFrameData, (mVideoWidth * mVideoHeight * 3) >> 1,
+                            mInputFrameData, (mWidth * mHeight * 3) >> 1,
                             inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen,
-                            mVideoWidth, mVideoHeight);
+                            mWidth, mHeight);
                 if (inputData == NULL) {
                     ALOGE("Unable to extract gralloc buffer in metadata mode");
                     mSignalledError = true;
@@ -677,9 +426,9 @@
                 }
             } else {
                 inputData = (const uint8_t *)inHeader->pBuffer + inHeader->nOffset;
-                if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+                if (mColorFormat != OMX_COLOR_FormatYUV420Planar) {
                     ConvertYUV420SemiPlanarToYUV420Planar(
-                        inputData, mInputFrameData, mVideoWidth, mVideoHeight);
+                        inputData, mInputFrameData, mWidth, mHeight);
                     inputData = mInputFrameData;
                 }
             }
@@ -689,8 +438,8 @@
             VideoEncFrameIO vin, vout;
             memset(&vin, 0, sizeof(vin));
             memset(&vout, 0, sizeof(vout));
-            vin.height = ((mVideoHeight  + 15) >> 4) << 4;
-            vin.pitch = ((mVideoWidth + 15) >> 4) << 4;
+            vin.height = align(mHeight, 16);
+            vin.pitch = align(mWidth, 16);
             vin.timestamp = (inHeader->nTimeStamp + 500) / 1000;  // in ms
             vin.yChan = (uint8_t *)inputData;
             vin.uChan = vin.yChan + vin.height * vin.pitch;
@@ -738,5 +487,19 @@
 android::SoftOMXComponent *createSoftOMXComponent(
         const char *name, const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
-    return new android::SoftMPEG4Encoder(name, callbacks, appData, component);
+    using namespace android;
+    if (!strcmp(name, "OMX.google.h263.encoder")) {
+        return new android::SoftMPEG4Encoder(
+                name, "video_encoder.h263", OMX_VIDEO_CodingH263, MEDIA_MIMETYPE_VIDEO_H263,
+                kH263ProfileLevels, NELEM(kH263ProfileLevels),
+                callbacks, appData, component);
+    } else if (!strcmp(name, "OMX.google.mpeg4.encoder")) {
+        return new android::SoftMPEG4Encoder(
+                name, "video_encoder.mpeg4", OMX_VIDEO_CodingMPEG4, MEDIA_MIMETYPE_VIDEO_MPEG4,
+                kMPEG4ProfileLevels, NELEM(kMPEG4ProfileLevels),
+                callbacks, appData, component);
+    } else {
+        CHECK(!"Unknown component");
+    }
+    return NULL;
 }
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
index b0605b4..3389c37 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.h
@@ -25,11 +25,16 @@
 
 namespace android {
 
-struct MediaBuffer;
+struct CodecProfileLevel;
 
 struct SoftMPEG4Encoder : public SoftVideoEncoderOMXComponent {
     SoftMPEG4Encoder(
             const char *name,
+            const char *componentRole,
+            OMX_VIDEO_CODINGTYPE codingType,
+            const char *mime,
+            const CodecProfileLevel *profileLevels,
+            size_t numProfileLevels,
             const OMX_CALLBACKTYPE *callbacks,
             OMX_PTR appData,
             OMX_COMPONENTTYPE **component);
@@ -58,12 +63,6 @@
     } InputBufferInfo;
 
     MP4EncodingMode mEncodeMode;
-    int32_t  mVideoWidth;
-    int32_t  mVideoHeight;
-    int32_t  mVideoFrameRate;
-    int32_t  mVideoBitRate;
-    int32_t  mVideoColorFormat;
-    bool     mStoreMetaDataInBuffers;
     int32_t  mIDRFrameRefreshIntervalInSec;
 
     int64_t  mNumInputFrames;
@@ -76,7 +75,6 @@
     uint8_t               *mInputFrameData;
     Vector<InputBufferInfo> mInputBufferInfoVec;
 
-    void initPorts();
     OMX_ERRORTYPE initEncParams();
     OMX_ERRORTYPE initEncoder();
     OMX_ERRORTYPE releaseEncoder();
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp
index fa4ae23..8d7d9f1 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp
@@ -267,7 +267,7 @@
     Void Block4x4DCT_AANwSub(Short *out, UChar *cur, UChar *pred, Int width)
     {
         Short *dst;
-        register Int k0, k1, k2, k3, k4, k5, k6, k7;
+        Int k0, k1, k2, k3, k4, k5, k6, k7;
         Int round;
         Int k12 = 0x022A02D4;
         Int k14 = 0x0188053A;
@@ -473,7 +473,7 @@
     Void Block2x2DCT_AANwSub(Short *out, UChar *cur, UChar *pred, Int width)
     {
         Short *dst;
-        register Int k0, k1, k2, k3, k4, k5, k6, k7;
+        Int k0, k1, k2, k3, k4, k5, k6, k7;
         Int round;
         Int k12 = 0x022A02D4;
         Int k14 = 0x018803B2;
@@ -863,7 +863,7 @@
     Void Block4x4DCT_AANIntra(Short *out, UChar *cur, UChar *dummy2, Int width)
     {
         Short *dst;
-        register Int k0, k1, k2, k3, k4, k5, k6, k7;
+        Int k0, k1, k2, k3, k4, k5, k6, k7;
         Int round;
         Int k12 = 0x022A02D4;
         Int k14 = 0x0188053A;
@@ -1050,7 +1050,7 @@
     Void Block2x2DCT_AANIntra(Short *out, UChar *cur, UChar *dummy2, Int width)
     {
         Short *dst;
-        register Int k0, k1, k2, k3, k4, k5, k6, k7;
+        Int k0, k1, k2, k3, k4, k5, k6, k7;
         Int round;
         Int k12 = 0x022A02D4;
         Int k14 = 0x018803B2;
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp
index 7ea5dc4..2aec815 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp
@@ -271,7 +271,7 @@
     Int ind;
     Int length;
 
-    if ((intra == 0))
+    if (intra == 0)
         cbpy = 15 - cbpy;
 
     ind = cbpy;
diff --git a/media/libstagefright/codecs/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
index 8284490..948ae29 100644
--- a/media/libstagefright/codecs/mp3dec/Android.mk
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -48,7 +48,7 @@
         $(LOCAL_PATH)/include
 
 LOCAL_CFLAGS := \
-        -DOSCL_UNUSED_ARG=
+        -D"OSCL_UNUSED_ARG(x)=(void)(x)"
 
 LOCAL_CFLAGS += -Werror
 
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index 87d6961..6e6a78a 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -38,19 +38,23 @@
             NULL /* profileLevels */, 0 /* numProfileLevels */,
             320 /* width */, 240 /* height */, callbacks, appData, component),
       mMode(codingType == OMX_VIDEO_CodingVP8 ? MODE_VP8 : MODE_VP9),
+      mEOSStatus(INPUT_DATA_AVAILABLE),
       mCtx(NULL),
+      mFrameParallelMode(false),
+      mTimeStampIdx(0),
       mImg(NULL) {
-    initPorts(kNumBuffers, 768 * 1024 /* inputBufferSize */,
-            kNumBuffers,
-            codingType == OMX_VIDEO_CodingVP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9);
-
+    // arbitrary from avc/hevc as vpx does not specify a min compression ratio
+    const size_t kMinCompressionRatio = mMode == MODE_VP8 ? 2 : 4;
+    const char *mime = mMode == MODE_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9;
+    const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
+    initPorts(
+            kNumBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* inputBufferSize */,
+            kNumBuffers, mime, kMinCompressionRatio);
     CHECK_EQ(initDecoder(), (status_t)OK);
 }
 
 SoftVPX::~SoftVPX() {
-    vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
-    delete (vpx_codec_ctx_t *)mCtx;
-    mCtx = NULL;
+    destroyDecoder();
 }
 
 static int GetCPUCoreCount() {
@@ -70,12 +74,19 @@
     mCtx = new vpx_codec_ctx_t;
     vpx_codec_err_t vpx_err;
     vpx_codec_dec_cfg_t cfg;
+    vpx_codec_flags_t flags;
     memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
+    memset(&flags, 0, sizeof(vpx_codec_flags_t));
     cfg.threads = GetCPUCoreCount();
+
+    if (mFrameParallelMode) {
+        flags |= VPX_CODEC_USE_FRAME_THREADING;
+    }
+
     if ((vpx_err = vpx_codec_dec_init(
                 (vpx_codec_ctx_t *)mCtx,
                  mMode == MODE_VP8 ? &vpx_codec_vp8_dx_algo : &vpx_codec_vp9_dx_algo,
-                 &cfg, 0))) {
+                 &cfg, flags))) {
         ALOGE("on2 decoder failed to initialize. (%d)", vpx_err);
         return UNKNOWN_ERROR;
     }
@@ -83,86 +94,155 @@
     return OK;
 }
 
+status_t SoftVPX::destroyDecoder() {
+    vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
+    delete (vpx_codec_ctx_t *)mCtx;
+    mCtx = NULL;
+    return OK;
+}
+
+bool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *portWillReset) {
+    List<BufferInfo *> &inQueue = getPortQueue(0);
+    List<BufferInfo *> &outQueue = getPortQueue(1);
+    BufferInfo *outInfo = NULL;
+    OMX_BUFFERHEADERTYPE *outHeader = NULL;
+    vpx_codec_iter_t iter = NULL;
+
+    if (flushDecoder && mFrameParallelMode) {
+        // Flush decoder by passing NULL data ptr and 0 size.
+        // Ideally, this should never fail.
+        if (vpx_codec_decode((vpx_codec_ctx_t *)mCtx, NULL, 0, NULL, 0)) {
+            ALOGE("Failed to flush on2 decoder.");
+            return false;
+        }
+    }
+
+    if (!display) {
+        if (!flushDecoder) {
+            ALOGE("Invalid operation.");
+            return false;
+        }
+        // Drop all the decoded frames in decoder.
+        while ((mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter))) {
+        }
+        return true;
+    }
+
+    while (!outQueue.empty()) {
+        if (mImg == NULL) {
+            mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
+            if (mImg == NULL) {
+                break;
+            }
+        }
+        uint32_t width = mImg->d_w;
+        uint32_t height = mImg->d_h;
+        outInfo = *outQueue.begin();
+        outHeader = outInfo->mHeader;
+        CHECK_EQ(mImg->fmt, IMG_FMT_I420);
+        handlePortSettingsChange(portWillReset, width, height);
+        if (*portWillReset) {
+            return true;
+        }
+
+        outHeader->nOffset = 0;
+        outHeader->nFilledLen = (width * height * 3) / 2;
+        outHeader->nFlags = 0;
+        outHeader->nTimeStamp = *(OMX_TICKS *)mImg->user_priv;
+
+        uint8_t *dst = outHeader->pBuffer;
+        const uint8_t *srcY = (const uint8_t *)mImg->planes[PLANE_Y];
+        const uint8_t *srcU = (const uint8_t *)mImg->planes[PLANE_U];
+        const uint8_t *srcV = (const uint8_t *)mImg->planes[PLANE_V];
+        size_t srcYStride = mImg->stride[PLANE_Y];
+        size_t srcUStride = mImg->stride[PLANE_U];
+        size_t srcVStride = mImg->stride[PLANE_V];
+        copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);
+
+        mImg = NULL;
+        outInfo->mOwnedByUs = false;
+        outQueue.erase(outQueue.begin());
+        outInfo = NULL;
+        notifyFillBufferDone(outHeader);
+        outHeader = NULL;
+    }
+
+    if (!eos) {
+        return true;
+    }
+
+    if (!outQueue.empty()) {
+        outInfo = *outQueue.begin();
+        outQueue.erase(outQueue.begin());
+        outHeader = outInfo->mHeader;
+        outHeader->nTimeStamp = 0;
+        outHeader->nFilledLen = 0;
+        outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+        outInfo->mOwnedByUs = false;
+        notifyFillBufferDone(outHeader);
+        mEOSStatus = OUTPUT_FRAMES_FLUSHED;
+    }
+    return true;
+}
+
 void SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) {
-    if (mOutputPortSettingsChange != NONE) {
+    if (mOutputPortSettingsChange != NONE || mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
         return;
     }
 
     List<BufferInfo *> &inQueue = getPortQueue(0);
     List<BufferInfo *> &outQueue = getPortQueue(1);
     bool EOSseen = false;
+    vpx_codec_err_t err;
+    bool portWillReset = false;
 
-    while (!inQueue.empty() && !outQueue.empty()) {
-        BufferInfo *inInfo = *inQueue.begin();
-        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
-
-        BufferInfo *outInfo = *outQueue.begin();
-        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
-
-        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
-            EOSseen = true;
-            if (inHeader->nFilledLen == 0) {
-                inQueue.erase(inQueue.begin());
-                inInfo->mOwnedByUs = false;
-                notifyEmptyBufferDone(inHeader);
-
-                outHeader->nFilledLen = 0;
-                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
-
-                outQueue.erase(outQueue.begin());
-                outInfo->mOwnedByUs = false;
-                notifyFillBufferDone(outHeader);
-                return;
-            }
-        }
-
-        if (mImg == NULL) {
-            if (vpx_codec_decode(
-                        (vpx_codec_ctx_t *)mCtx,
-                        inHeader->pBuffer + inHeader->nOffset,
-                        inHeader->nFilledLen,
-                        NULL,
-                        0)) {
-                ALOGE("on2 decoder failed to decode frame.");
-
+    while ((mEOSStatus == INPUT_EOS_SEEN || !inQueue.empty())
+            && !outQueue.empty()) {
+        // Output the pending frames that left from last port reset or decoder flush.
+        if (mEOSStatus == INPUT_EOS_SEEN || mImg != NULL) {
+            if (!outputBuffers(
+                     mEOSStatus == INPUT_EOS_SEEN, true /* display */,
+                     mEOSStatus == INPUT_EOS_SEEN, &portWillReset)) {
+                ALOGE("on2 decoder failed to output frame.");
                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
                 return;
             }
-            vpx_codec_iter_t iter = NULL;
-            mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
-        }
-
-        if (mImg != NULL) {
-            CHECK_EQ(mImg->fmt, IMG_FMT_I420);
-
-            uint32_t width = mImg->d_w;
-            uint32_t height = mImg->d_h;
-            bool portWillReset = false;
-            handlePortSettingsChange(&portWillReset, width, height);
-            if (portWillReset) {
+            if (portWillReset || mEOSStatus == OUTPUT_FRAMES_FLUSHED ||
+                    mEOSStatus == INPUT_EOS_SEEN) {
                 return;
             }
+        }
 
-            outHeader->nOffset = 0;
-            outHeader->nFilledLen = (width * height * 3) / 2;
-            outHeader->nFlags = EOSseen ? OMX_BUFFERFLAG_EOS : 0;
-            outHeader->nTimeStamp = inHeader->nTimeStamp;
+        BufferInfo *inInfo = *inQueue.begin();
+        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+        mTimeStamps[mTimeStampIdx] = inHeader->nTimeStamp;
 
-            uint8_t *dst = outHeader->pBuffer;
-            const uint8_t *srcY = (const uint8_t *)mImg->planes[PLANE_Y];
-            const uint8_t *srcU = (const uint8_t *)mImg->planes[PLANE_U];
-            const uint8_t *srcV = (const uint8_t *)mImg->planes[PLANE_V];
-            size_t srcYStride = mImg->stride[PLANE_Y];
-            size_t srcUStride = mImg->stride[PLANE_U];
-            size_t srcVStride = mImg->stride[PLANE_V];
-            copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride);
+        BufferInfo *outInfo = *outQueue.begin();
+        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+            mEOSStatus = INPUT_EOS_SEEN;
+            EOSseen = true;
+        }
 
-            mImg = NULL;
-            outInfo->mOwnedByUs = false;
-            outQueue.erase(outQueue.begin());
-            outInfo = NULL;
-            notifyFillBufferDone(outHeader);
-            outHeader = NULL;
+        if (inHeader->nFilledLen > 0 &&
+            vpx_codec_decode((vpx_codec_ctx_t *)mCtx,
+                              inHeader->pBuffer + inHeader->nOffset,
+                              inHeader->nFilledLen,
+                              &mTimeStamps[mTimeStampIdx], 0)) {
+            ALOGE("on2 decoder failed to decode frame.");
+            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+            return;
+        }
+        mTimeStampIdx = (mTimeStampIdx + 1) % kNumBuffers;
+
+        if (!outputBuffers(
+                 EOSseen /* flushDecoder */, true /* display */, EOSseen, &portWillReset)) {
+            ALOGE("on2 decoder failed to output frame.");
+            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+            return;
+        }
+        if (portWillReset) {
+            return;
         }
 
         inInfo->mOwnedByUs = false;
@@ -173,6 +253,30 @@
     }
 }
 
+void SoftVPX::onPortFlushCompleted(OMX_U32 portIndex) {
+    if (portIndex == kInputPortIndex) {
+        bool portWillReset = false;
+        if (!outputBuffers(
+                 true /* flushDecoder */, false /* display */, false /* eos */, &portWillReset)) {
+            ALOGE("Failed to flush decoder.");
+            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+            return;
+        }
+        mEOSStatus = INPUT_DATA_AVAILABLE;
+    }
+}
+
+void SoftVPX::onReset() {
+    bool portWillReset = false;
+    if (!outputBuffers(
+             true /* flushDecoder */, false /* display */, false /* eos */, &portWillReset)) {
+        ALOGW("Failed to flush decoder. Try to hard reset decoder");
+        destroyDecoder();
+        initDecoder();
+    }
+    mEOSStatus = INPUT_DATA_AVAILABLE;
+}
+
 }  // namespace android
 
 android::SoftOMXComponent *createSoftOMXComponent(
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.h b/media/libstagefright/codecs/on2/dec/SoftVPX.h
index 8f68693..8ccbae2 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.h
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.h
@@ -38,6 +38,8 @@
     virtual ~SoftVPX();
 
     virtual void onQueueFilled(OMX_U32 portIndex);
+    virtual void onPortFlushCompleted(OMX_U32 portIndex);
+    virtual void onReset();
 
 private:
     enum {
@@ -49,11 +51,21 @@
         MODE_VP9
     } mMode;
 
-    void *mCtx;
+    enum {
+        INPUT_DATA_AVAILABLE,  // VPX component is ready to decode data.
+        INPUT_EOS_SEEN,        // VPX component saw EOS and is flushing On2 decoder.
+        OUTPUT_FRAMES_FLUSHED  // VPX component finished flushing On2 decoder.
+    } mEOSStatus;
 
+    void *mCtx;
+    bool mFrameParallelMode;  // Frame parallel is only supported by VP9 decoder.
+    OMX_TICKS mTimeStamps[kNumBuffers];
+    uint8_t mTimeStampIdx;
     vpx_image_t *mImg;
 
     status_t initDecoder();
+    status_t destroyDecoder();
+    bool outputBuffers(bool flushDecoder, bool display, bool eos, bool *portWillReset);
 
     DISALLOW_EVIL_CONSTRUCTORS(SoftVPX);
 };
diff --git a/media/libstagefright/codecs/on2/enc/Android.mk b/media/libstagefright/codecs/on2/enc/Android.mk
index e265104..253fa04 100644
--- a/media/libstagefright/codecs/on2/enc/Android.mk
+++ b/media/libstagefright/codecs/on2/enc/Android.mk
@@ -6,7 +6,6 @@
 
 LOCAL_C_INCLUDES := \
         $(TOP)/external/libvpx/libvpx \
-        $(TOP)/external/openssl/include \
         $(TOP)/external/libvpx/libvpx/vpx_codec \
         $(TOP)/external/libvpx/libvpx/vpx_ports \
         frameworks/av/media/libstagefright/include \
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index 0285feb..970acf3 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -19,6 +19,7 @@
 #include "SoftVPXEncoder.h"
 
 #include <utils/Log.h>
+#include <utils/misc.h>
 
 #include <media/hardware/HardwareAPI.h>
 #include <media/hardware/MetadataBufferType.h>
@@ -50,23 +51,29 @@
     return cpuCoreCount;
 }
 
+static const CodecProfileLevel kProfileLevels[] = {
+    { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version0 },
+    { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version1 },
+    { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version2 },
+    { OMX_VIDEO_VP8ProfileMain, OMX_VIDEO_VP8Level_Version3 },
+};
+
 SoftVPXEncoder::SoftVPXEncoder(const char *name,
                                const OMX_CALLBACKTYPE *callbacks,
                                OMX_PTR appData,
                                OMX_COMPONENTTYPE **component)
-    : SoftVideoEncoderOMXComponent(name, callbacks, appData, component),
+    : SoftVideoEncoderOMXComponent(
+            name, "video_encoder.vp8", OMX_VIDEO_CodingVP8,
+            kProfileLevels, NELEM(kProfileLevels),
+            176 /* width */, 144 /* height */,
+            callbacks, appData, component),
       mCodecContext(NULL),
       mCodecConfiguration(NULL),
       mCodecInterface(NULL),
-      mWidth(176),
-      mHeight(144),
-      mBitrate(192000),  // in bps
-      mFramerate(30 << 16), // in Q16 format
       mBitrateUpdated(false),
       mBitrateControlMode(VPX_VBR),  // variable bitrate
       mDCTPartitions(0),
       mErrorResilience(OMX_FALSE),
-      mColorFormat(OMX_COLOR_FormatYUV420Planar),
       mLevel(OMX_VIDEO_VP8Level_Version0),
       mKeyFrameInterval(0),
       mMinQuantizer(0),
@@ -77,11 +84,15 @@
       mTemporalPatternIdx(0),
       mLastTimestamp(0x7FFFFFFFFFFFFFFFLL),
       mConversionBuffer(NULL),
-      mInputDataIsMeta(false),
       mKeyFrameRequested(false) {
     memset(mTemporalLayerBitrateRatio, 0, sizeof(mTemporalLayerBitrateRatio));
     mTemporalLayerBitrateRatio[0] = 100;
-    initPorts();
+
+    const size_t kMinOutputBufferSize = 1024 * 1024; // arbitrary
+
+    initPorts(
+            kNumBuffers, kNumBuffers, kMinOutputBufferSize,
+            MEDIA_MIMETYPE_VIDEO_VP8, 2 /* minCompressionRatio */);
 }
 
 
@@ -89,71 +100,6 @@
     releaseEncoder();
 }
 
-
-void SoftVPXEncoder::initPorts() {
-    OMX_PARAM_PORTDEFINITIONTYPE inputPort;
-    OMX_PARAM_PORTDEFINITIONTYPE outputPort;
-
-    InitOMXParams(&inputPort);
-    InitOMXParams(&outputPort);
-
-    inputPort.nBufferCountMin = kNumBuffers;
-    inputPort.nBufferCountActual = inputPort.nBufferCountMin;
-    inputPort.bEnabled = OMX_TRUE;
-    inputPort.bPopulated = OMX_FALSE;
-    inputPort.eDomain = OMX_PortDomainVideo;
-    inputPort.bBuffersContiguous = OMX_FALSE;
-    inputPort.format.video.pNativeRender = NULL;
-    inputPort.format.video.nFrameWidth = mWidth;
-    inputPort.format.video.nFrameHeight = mHeight;
-    inputPort.format.video.nStride = inputPort.format.video.nFrameWidth;
-    inputPort.format.video.nSliceHeight = inputPort.format.video.nFrameHeight;
-    inputPort.format.video.nBitrate = 0;
-    // frameRate is in Q16 format.
-    inputPort.format.video.xFramerate = mFramerate;
-    inputPort.format.video.bFlagErrorConcealment = OMX_FALSE;
-    inputPort.nPortIndex = kInputPortIndex;
-    inputPort.eDir = OMX_DirInput;
-    inputPort.nBufferAlignment = kInputBufferAlignment;
-    inputPort.format.video.cMIMEType =
-        const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
-    inputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
-    inputPort.format.video.eColorFormat = mColorFormat;
-    inputPort.format.video.pNativeWindow = NULL;
-    inputPort.nBufferSize =
-        (inputPort.format.video.nStride *
-        inputPort.format.video.nSliceHeight * 3) / 2;
-
-    addPort(inputPort);
-
-    outputPort.nBufferCountMin = kNumBuffers;
-    outputPort.nBufferCountActual = outputPort.nBufferCountMin;
-    outputPort.bEnabled = OMX_TRUE;
-    outputPort.bPopulated = OMX_FALSE;
-    outputPort.eDomain = OMX_PortDomainVideo;
-    outputPort.bBuffersContiguous = OMX_FALSE;
-    outputPort.format.video.pNativeRender = NULL;
-    outputPort.format.video.nFrameWidth = mWidth;
-    outputPort.format.video.nFrameHeight = mHeight;
-    outputPort.format.video.nStride = outputPort.format.video.nFrameWidth;
-    outputPort.format.video.nSliceHeight = outputPort.format.video.nFrameHeight;
-    outputPort.format.video.nBitrate = mBitrate;
-    outputPort.format.video.xFramerate = 0;
-    outputPort.format.video.bFlagErrorConcealment = OMX_FALSE;
-    outputPort.nPortIndex = kOutputPortIndex;
-    outputPort.eDir = OMX_DirOutput;
-    outputPort.nBufferAlignment = kOutputBufferAlignment;
-    outputPort.format.video.cMIMEType =
-        const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VP8);
-    outputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8;
-    outputPort.format.video.eColorFormat = OMX_COLOR_FormatUnused;
-    outputPort.format.video.pNativeWindow = NULL;
-    outputPort.nBufferSize = 1024 * 1024; // arbitrary
-
-    addPort(outputPort);
-}
-
-
 status_t SoftVPXEncoder::initEncoder() {
     vpx_codec_err_t codec_return;
 
@@ -409,38 +355,6 @@
     const int32_t indexFull = index;
 
     switch (indexFull) {
-        case OMX_IndexParamVideoPortFormat: {
-            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
-                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
-
-            if (formatParams->nPortIndex == kInputPortIndex) {
-                if (formatParams->nIndex >= kNumberOfSupportedColorFormats) {
-                    return OMX_ErrorNoMore;
-                }
-
-                // Color formats, in order of preference
-                if (formatParams->nIndex == 0) {
-                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
-                } else if (formatParams->nIndex == 1) {
-                    formatParams->eColorFormat =
-                        OMX_COLOR_FormatYUV420SemiPlanar;
-                } else {
-                    formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
-                }
-
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
-                formatParams->xFramerate = mFramerate;
-                return OMX_ErrorNone;
-            } else if (formatParams->nPortIndex == kOutputPortIndex) {
-                formatParams->eCompressionFormat = OMX_VIDEO_CodingVP8;
-                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
-                formatParams->xFramerate = 0;
-                return OMX_ErrorNone;
-            } else {
-                return OMX_ErrorBadPortIndex;
-            }
-        }
-
         case OMX_IndexParamVideoBitrate: {
             OMX_VIDEO_PARAM_BITRATETYPE *bitrate =
                 (OMX_VIDEO_PARAM_BITRATETYPE *)param;
@@ -495,54 +409,8 @@
                 return OMX_ErrorNone;
         }
 
-        case OMX_IndexParamVideoProfileLevelQuerySupported: {
-            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel =
-                (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param;
-
-            if (profileAndLevel->nPortIndex != kOutputPortIndex) {
-                return OMX_ErrorUnsupportedIndex;
-            }
-
-            switch (profileAndLevel->nProfileIndex) {
-                case 0:
-                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version0;
-                    break;
-
-                case 1:
-                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version1;
-                    break;
-
-                case 2:
-                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version2;
-                    break;
-
-                case 3:
-                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version3;
-                    break;
-
-                default:
-                    return OMX_ErrorNoMore;
-            }
-
-            profileAndLevel->eProfile = OMX_VIDEO_VP8ProfileMain;
-            return OMX_ErrorNone;
-        }
-
-        case OMX_IndexParamVideoProfileLevelCurrent: {
-            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel =
-                (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param;
-
-            if (profileAndLevel->nPortIndex != kOutputPortIndex) {
-                return OMX_ErrorUnsupportedIndex;
-            }
-
-            profileAndLevel->eLevel = mLevel;
-            profileAndLevel->eProfile = OMX_VIDEO_VP8ProfileMain;
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalGetParameter(index, param);
+            return SoftVideoEncoderOMXComponent::internalGetParameter(index, param);
     }
 }
 
@@ -553,30 +421,10 @@
     const int32_t indexFull = index;
 
     switch (indexFull) {
-        case OMX_IndexParamStandardComponentRole:
-            return internalSetRoleParams(
-                (const OMX_PARAM_COMPONENTROLETYPE *)param);
-
         case OMX_IndexParamVideoBitrate:
             return internalSetBitrateParams(
                 (const OMX_VIDEO_PARAM_BITRATETYPE *)param);
 
-        case OMX_IndexParamPortDefinition:
-        {
-            OMX_ERRORTYPE err = internalSetPortParams(
-                (const OMX_PARAM_PORTDEFINITIONTYPE *)param);
-
-            if (err != OMX_ErrorNone) {
-                return err;
-            }
-
-            return SimpleSoftOMXComponent::internalSetParameter(index, param);
-        }
-
-        case OMX_IndexParamVideoPortFormat:
-            return internalSetFormatParams(
-                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param);
-
         case OMX_IndexParamVideoVp8:
             return internalSetVp8Params(
                 (const OMX_VIDEO_PARAM_VP8TYPE *)param);
@@ -585,27 +433,8 @@
             return internalSetAndroidVp8Params(
                 (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param);
 
-        case OMX_IndexParamVideoProfileLevelCurrent:
-            return internalSetProfileLevel(
-                (const OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param);
-
-        case kStoreMetaDataExtensionIndex:
-        {
-            // storeMetaDataInBuffers
-            const StoreMetaDataInBuffersParams *storeParam =
-                (const StoreMetaDataInBuffersParams *)param;
-
-            if (storeParam->nPortIndex != kInputPortIndex) {
-                return OMX_ErrorBadPortIndex;
-            }
-
-            mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE);
-
-            return OMX_ErrorNone;
-        }
-
         default:
-            return SimpleSoftOMXComponent::internalSetParameter(index, param);
+            return SoftVideoEncoderOMXComponent::internalSetParameter(index, param);
     }
 }
 
@@ -646,29 +475,6 @@
     }
 }
 
-OMX_ERRORTYPE SoftVPXEncoder::internalSetProfileLevel(
-        const OMX_VIDEO_PARAM_PROFILELEVELTYPE* profileAndLevel) {
-    if (profileAndLevel->nPortIndex != kOutputPortIndex) {
-        return OMX_ErrorUnsupportedIndex;
-    }
-
-    if (profileAndLevel->eProfile != OMX_VIDEO_VP8ProfileMain) {
-        return OMX_ErrorBadParameter;
-    }
-
-    if (profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version0 ||
-        profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version1 ||
-        profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version2 ||
-        profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version3) {
-        mLevel = (OMX_VIDEO_VP8LEVELTYPE)profileAndLevel->eLevel;
-    } else {
-        return OMX_ErrorBadParameter;
-    }
-
-    return OMX_ErrorNone;
-}
-
-
 OMX_ERRORTYPE SoftVPXEncoder::internalSetVp8Params(
         const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
     if (vp8Params->nPortIndex != kOutputPortIndex) {
@@ -743,95 +549,6 @@
     return OMX_ErrorNone;
 }
 
-OMX_ERRORTYPE SoftVPXEncoder::internalSetFormatParams(
-        const OMX_VIDEO_PARAM_PORTFORMATTYPE* format) {
-    if (format->nPortIndex == kInputPortIndex) {
-        if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
-            format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
-            format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
-            mColorFormat = format->eColorFormat;
-
-            OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
-            def->format.video.eColorFormat = mColorFormat;
-
-            return OMX_ErrorNone;
-        } else {
-            ALOGE("Unsupported color format %i", format->eColorFormat);
-            return OMX_ErrorUnsupportedSetting;
-        }
-    } else if (format->nPortIndex == kOutputPortIndex) {
-        if (format->eCompressionFormat == OMX_VIDEO_CodingVP8) {
-            return OMX_ErrorNone;
-        } else {
-            return OMX_ErrorUnsupportedSetting;
-        }
-    } else {
-        return OMX_ErrorBadPortIndex;
-    }
-}
-
-
-OMX_ERRORTYPE SoftVPXEncoder::internalSetRoleParams(
-        const OMX_PARAM_COMPONENTROLETYPE* role) {
-    const char* roleText = (const char*)role->cRole;
-    const size_t roleTextMaxSize = OMX_MAX_STRINGNAME_SIZE - 1;
-
-    if (strncmp(roleText, "video_encoder.vp8", roleTextMaxSize)) {
-        ALOGE("Unsupported component role");
-        return OMX_ErrorBadParameter;
-    }
-
-    return OMX_ErrorNone;
-}
-
-
-OMX_ERRORTYPE SoftVPXEncoder::internalSetPortParams(
-        const OMX_PARAM_PORTDEFINITIONTYPE* port) {
-    if (port->nPortIndex == kInputPortIndex) {
-        mWidth = port->format.video.nFrameWidth;
-        mHeight = port->format.video.nFrameHeight;
-
-        // xFramerate comes in Q16 format, in frames per second unit
-        mFramerate = port->format.video.xFramerate;
-
-        if (port->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar ||
-            port->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
-            port->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
-            mColorFormat = port->format.video.eColorFormat;
-        } else {
-            return OMX_ErrorUnsupportedSetting;
-        }
-
-        OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
-        def->format.video.nFrameWidth = mWidth;
-        def->format.video.nFrameHeight = mHeight;
-        def->format.video.nStride = def->format.video.nFrameWidth;
-        def->format.video.nSliceHeight = def->format.video.nFrameHeight;
-        def->format.video.xFramerate = mFramerate;
-        def->format.video.eColorFormat = mColorFormat;
-        def->nBufferSize =
-            (def->format.video.nStride * def->format.video.nSliceHeight * 3) / 2;
-        def = &editPortInfo(kOutputPortIndex)->mDef;
-        def->format.video.nFrameWidth = mWidth;
-        def->format.video.nFrameHeight = mHeight;
-
-        return OMX_ErrorNone;
-    } else if (port->nPortIndex == kOutputPortIndex) {
-        mBitrate = port->format.video.nBitrate;
-        mWidth = port->format.video.nFrameWidth;
-        mHeight = port->format.video.nFrameHeight;
-
-        OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
-        def->format.video.nFrameWidth = mWidth;
-        def->format.video.nFrameHeight = mHeight;
-        def->format.video.nBitrate = mBitrate;
-        return OMX_ErrorNone;
-    } else {
-        return OMX_ErrorBadPortIndex;
-    }
-}
-
-
 OMX_ERRORTYPE SoftVPXEncoder::internalSetBitrateParams(
         const OMX_VIDEO_PARAM_BITRATETYPE* bitrate) {
     if (bitrate->nPortIndex != kOutputPortIndex) {
@@ -920,7 +637,7 @@
     return flags;
 }
 
-void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) {
+void SoftVPXEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
     // Initialize encoder if not already
     if (mCodecContext == NULL) {
         if (OK != initEncoder()) {
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
index f4c1564..cd0a0cf 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.h
@@ -155,18 +155,6 @@
     // that specifies algorithm interface (e.g. vp8)
     vpx_codec_iface_t* mCodecInterface;
 
-    // Width of the input frames
-    int32_t mWidth;
-
-    // Height of the input frames
-    int32_t mHeight;
-
-    // Target bitrate set for the encoder, in bits per second.
-    uint32_t mBitrate;
-
-    // Target framerate set for the encoder.
-    uint32_t mFramerate;
-
     // If a request for a change it bitrate has been received.
     bool mBitrateUpdated;
 
@@ -182,9 +170,6 @@
     // is enabled in encoder
     OMX_BOOL mErrorResilience;
 
-    // Color format for the input port
-    OMX_COLOR_FORMATTYPE mColorFormat;
-
     // Encoder profile corresponding to OMX level parameter
     //
     // The inconsistency in the naming is caused by
@@ -229,14 +214,8 @@
     // indeed YUV420SemiPlanar.
     uint8_t* mConversionBuffer;
 
-    bool mInputDataIsMeta;
-
     bool mKeyFrameRequested;
 
-    // Initializes input and output OMX ports with sensible
-    // default values.
-    void initPorts();
-
     // Initializes vpx encoder with available settings.
     status_t initEncoder();
 
@@ -250,23 +229,10 @@
     // Get current encode flags
     vpx_enc_frame_flags_t getEncodeFlags();
 
-    // Handles port changes with respect to color formats
-    OMX_ERRORTYPE internalSetFormatParams(
-        const OMX_VIDEO_PARAM_PORTFORMATTYPE* format);
-
-    // Verifies the component role tried to be set to this OMX component is
-    // strictly video_encoder.vp8
-    OMX_ERRORTYPE internalSetRoleParams(
-        const OMX_PARAM_COMPONENTROLETYPE* role);
-
     // Updates bitrate to reflect port settings.
     OMX_ERRORTYPE internalSetBitrateParams(
         const OMX_VIDEO_PARAM_BITRATETYPE* bitrate);
 
-    // Handles port definition changes.
-    OMX_ERRORTYPE internalSetPortParams(
-        const OMX_PARAM_PORTDEFINITIONTYPE* port);
-
     // Handles vp8 specific parameters.
     OMX_ERRORTYPE internalSetVp8Params(
         const OMX_VIDEO_PARAM_VP8TYPE* vp8Params);
@@ -275,10 +241,6 @@
     OMX_ERRORTYPE internalSetAndroidVp8Params(
         const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams);
 
-    // Updates encoder profile
-    OMX_ERRORTYPE internalSetProfileLevel(
-        const OMX_VIDEO_PARAM_PROFILELEVELTYPE* profileAndLevel);
-
     DISALLOW_EVIL_CONSTRUCTORS(SoftVPXEncoder);
 };
 
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index 168208f..6b8b395 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -64,9 +64,11 @@
       mHeadersDecoded(false),
       mEOSStatus(INPUT_DATA_AVAILABLE),
       mSignalledError(false) {
+    const size_t kMinCompressionRatio = 2;
+    const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2;
     initPorts(
-            kNumInputBuffers, 8192 /* inputBufferSize */,
-            kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC);
+            kNumInputBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* minInputBufferSize */,
+            kNumOutputBuffers, MEDIA_MIMETYPE_VIDEO_AVC, kMinCompressionRatio);
 
     CHECK_EQ(initDecoder(), (status_t)OK);
 }
diff --git a/media/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h b/media/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/inc/basetype.h b/media/libstagefright/codecs/on2/h264dec/inc/basetype.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM.h
index 2ed86a4..fbb97e2 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *   
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_BitDec_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_BitDec_s.h
index abb98fc..d5866fa 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_BitDec_s.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_BitDec_s.h
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armCOMM_BitDec_s.h
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;// 
@@ -667,4 +681,4 @@
         MEND
         
         END
-        
\ No newline at end of file
+        
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Bitstream.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Bitstream.h
index 4f9bc3b..576b66d 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Bitstream.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Bitstream.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM_Bitstream.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCTTable.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCTTable.h
index d5db32f..223684e 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCTTable.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCTTable.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCT_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCT_s.h
index 03f7137..6a7d24f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCT_s.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCT_s.h
@@ -1,11 +1,19 @@
 ;//
-;// This confidential and proprietary software may be used only as
-;// authorised by a licensing agreement from ARM Limited
-;//   (C) COPYRIGHT 2004 ARM Limited
-;//       ALL RIGHTS RESERVED
-;// The entire notice above must be reproduced on all authorised
-;// copies and copies may only be made to the extent permitted
-;// by a licensing agreement from ARM Limited.
+;// Copyright (C) 2004 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;//
 ;// IDCT_s.s
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_MaskTable.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_MaskTable.h
index b5da9dc..5246f15 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_MaskTable.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_MaskTable.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM_MaskTable.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_s.h
index 2df1fc8..04735a9 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_s.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_s.h
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armCOMM_s.h
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armOMX.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armOMX.h
index f629f72..e7c0c26 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armOMX.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armOMX.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* 
  * 
  * File Name:  armOMX_ReleaseVersion.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes_s.h
index 8d24b65..d41a037 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes_s.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes_s.h
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxtypes_s.h
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/build_vc.pl b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/build_vc.pl
index 1ae7005..5d672b3 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/build_vc.pl
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/build_vc.pl
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 #!/usr/bin/perl
 #
 # 
@@ -6,7 +22,6 @@
 # Revision:   9641
 # Date:       Thursday, February 7, 2008
 # 
-# (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 # 
 # 
 #
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM.c
index e572a89..e8dbf41 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_Bitstream.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_Bitstream.c
index 9ef9319..99f53ca 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_Bitstream.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_Bitstream.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM_Bitstream.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_IDCTTable.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_IDCTTable.c
index 9e4679c..6f0b87f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_IDCTTable.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_IDCTTable.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM_IDCTTable.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *   
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_MaskTable.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_MaskTable.c
index 3241db2..906a8e5 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_MaskTable.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_MaskTable.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVC.h
index 7fa7716..6dbe8b6 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVC.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVC.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVCCOMM_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVCCOMM_s.h
index 7f0a9b8..a9d4644 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVCCOMM_s.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVCCOMM_s.h
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCCOMM_s.h
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -69,4 +83,4 @@
         
     ENDIF ;// ARMACCOMM_S_H
 
- END
\ No newline at end of file
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
index 02b4b08..f5d2271 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCCOMM_ExpandFrame_I_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -186,4 +200,4 @@
     ENDIF                                                    ;//ARM1136JS        
  
             
-    END
\ No newline at end of file
+    END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/api/armVCM4P10_CAVLCTables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/api/armVCM4P10_CAVLCTables.h
index 4340f2a..d43d86b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/api/armVCM4P10_CAVLCTables.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/api/armVCM4P10_CAVLCTables.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  * 
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
index b2cd9d1..198f0ac 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_Average_4x_Align_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -219,4 +233,4 @@
     ENDIF
     
     END
-    
\ No newline at end of file
+    
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_CAVLCTables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_CAVLCTables.c
index 17fe518..3b84c8d 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_CAVLCTables.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_CAVLCTables.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
index dcbcd00..51dcb92 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_DeblockingChroma_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -17,4 +31,4 @@
 
 
 
-        END
\ No newline at end of file
+        END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
index 14b37fe..2085233 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_DeblockingLuma_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -363,4 +377,4 @@
     
     ENDIF
 
-        END
\ No newline at end of file
+        END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
index ac448a0..33638bf 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_DecodeCoeffsToPair_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DequantTables_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DequantTables_s.s
index b16f188..afe07b5 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DequantTables_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DequantTables_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_DequantTables_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -120,4 +134,4 @@
 
                            
     
-         END
\ No newline at end of file
+         END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
index 82b9542..ffe123d 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_Align_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
index bc0b6ec..c9a89fd 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -146,4 +160,4 @@
     ENDIF
 
     END
-    
\ No newline at end of file
+    
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
index 66cfe5e..98b67eb 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -175,4 +189,4 @@
     ENDIF
     
     END
-    
\ No newline at end of file
+    
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
index 851ff6a..523eace 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
index 2f48e13..2e7c5c7 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
index 6690ced..81af75a 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
index 007cd0d..906cbf3 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -182,4 +196,4 @@
     ENDIF
     
     END
-    
\ No newline at end of file
+    
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
index b1ad17c..35bf67c 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_Interpolate_Chroma_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_QuantTables_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_QuantTables_s.s
index f962f70..938c719 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_QuantTables_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_QuantTables_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_QuantTables_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;// Description:
@@ -71,4 +85,4 @@
          
          
          END
-         
\ No newline at end of file
+         
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
index 241d188..e5372e1 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_TransformResidual4x4_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -404,4 +418,4 @@
 ;// Guarding implementation by the processor name
     
             
-    END
\ No newline at end of file
+    END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
index ad16d9c..d02b4f3 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_UnpackBlock4x4_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -89,4 +103,4 @@
     
     
     END
-    
\ No newline at end of file
+    
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
index c2e6b60..34adea8 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
index 6023862..8b47dc2 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
index a19f277..2cd65ca 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
index 99bb4ce..9f9706b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
index 2b71486..3187f2b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
@@ -1,5 +1,19 @@
 ;//
-;// (c) Copyright 2007 ARM Limited. All Rights Reserved.
+;// Copyright (C) 2007 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;//
 ;// Description:
 ;// H.264 inverse quantize and transform module
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
index 6d960f0..d940418 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
index 00c8354..2dc9369 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
index 1b84080..e4fbfa4 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -328,4 +342,4 @@
 
         END
         
-        
\ No newline at end of file
+        
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
index 417ddc2..6adf27b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -547,4 +561,4 @@
         
         END
         
-        
\ No newline at end of file
+        
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
index de835bd..63d185f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_InterpolateChroma.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
index cf611a3..cb3b4e2 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_InterpolateLuma_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -423,4 +437,4 @@
                     
 
     END
-    
\ No newline at end of file
+    
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
index 34fedd8..09b4cf6 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_PredictIntraChroma_8x8_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
index 1557208..0c0cba7 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_PredictIntra_16x16_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
index a90f460..112139f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_PredictIntra_4x4_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
index 53597a8..b83d7f0 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_TransformDequantChromaDCFromPair_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
index 73caec2..6974cd1 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_TransformDequantLumaDCFromPair_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -466,4 +480,4 @@
     ENDIF                                                           ;//ARM1136JS  
     
 
-    END
\ No newline at end of file
+    END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
index 22115d3..359e752 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_Huff_Tables_VLC.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
index d5f865c..286ba04 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_ZigZag_Tables.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Clip8_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Clip8_s.s
index 7801e57..241d441 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Clip8_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Clip8_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ; /**
 ; * 
 ; * File Name:  armVCM4P2_Clip8_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   9641
 ; * Date:       Thursday, February 7, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
index 9e30900..96f5bed 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   9641
 ; * Date:       Thursday, February 7, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
index ba4d058..04d86ed 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
  /**
  * 
  * File Name:  armVCM4P2_Huff_Tables_VLC.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Lookup_Tables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
index 25cf8db..04739a5 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
  /**
  * 
  * File Name:  armVCM4P2_Lookup_Tables.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_SetPredDir_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
index 3f92d85..d0d13d1 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P2_SetPredDir_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
index ed17f9b..b647559 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_Zigzag_Tables.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
index b63d295..127772a 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DecodeBlockCoef_Inter.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
index c609a60..f24fc07 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DecodeBlockCoef_Intra.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
index a1861da..65a01d7 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ; **********
 ; * 
 ; * File Name:  omxVCM4P2_DecodePadMV_PVOP_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   9641
 ; * Date:       Thursday, February 7, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
index c43b253..5ee33d8 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  omxVCM4P2_DecodeVLCZigzag_Inter_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   9641
 ; * Date:       Thursday, February 7, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
index 166729e..9d5940c 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   9641
 ; * Date:       Thursday, February 7, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
index d19cb13..266a62b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   9641
 ; * Date:       Thursday, February 7, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
index a4bfa71..92acd51 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P2_FindMVpred_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -191,4 +205,4 @@
         M_END
     ENDIF ;// ARM1136JS :LOR: CortexA8
     
-    END
\ No newline at end of file
+    END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
index bfeb540..e4f91fb 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P2_IDCT8x8blk_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
index 20965bf..8ac6ff9 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P2_MCReconBlock_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
index 213444a..116c81d 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ; **********
 ; * 
 ; * File Name:  omxVCM4P2_PredictReconCoefIntra_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   9641
 ; * Date:       Thursday, February 7, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
index c9591cb..d57160f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  omxVCM4P2_QuantInvInter_I_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   9641
 ; * Date:       Thursday, February 7, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
index 6328e01..bd82da4 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  omxVCM4P2_QuantInvIntra_I_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   9641
 ; * Date:       Thursday, February 7, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
old mode 100755
new mode 100644
index 64c1958..91e38b8
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM.h
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *   
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_BitDec_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_BitDec_s.h
old mode 100755
new mode 100644
index c738f72..56344e3
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_BitDec_s.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_BitDec_s.h
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armCOMM_BitDec_s.h
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;// 
@@ -667,4 +681,4 @@
         MEND
         
         END
-        
\ No newline at end of file
+        
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Bitstream.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Bitstream.h
old mode 100755
new mode 100644
index b699034..8c0ef37
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Bitstream.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Bitstream.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM_Bitstream.h
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCTTable.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCTTable.h
old mode 100755
new mode 100644
index e0cfdaa..d761f61
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCTTable.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCTTable.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCT_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCT_s.h
old mode 100755
new mode 100644
index 0baa087..9130223
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCT_s.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCT_s.h
@@ -1,11 +1,19 @@
 ;//
-;// This confidential and proprietary software may be used only as
-;// authorised by a licensing agreement from ARM Limited
-;//   (C) COPYRIGHT 2004 ARM Limited
-;//       ALL RIGHTS RESERVED
-;// The entire notice above must be reproduced on all authorised
-;// copies and copies may only be made to the extent permitted
-;// by a licensing agreement from ARM Limited.
+;// Copyright (C) 2004 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;//
 ;// IDCT_s.s
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_MaskTable.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_MaskTable.h
old mode 100755
new mode 100644
index 51118fd..5ffc835
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_MaskTable.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_MaskTable.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM_MaskTable.h
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Version.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Version.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_s.h
old mode 100755
new mode 100644
index 0956bd1..321d2d3
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_s.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_s.h
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armCOMM_s.h
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armOMX.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armOMX.h
old mode 100755
new mode 100644
index 7a68d14..303abd9
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armOMX.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armOMX.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* 
  * 
  * File Name:  armOMX_ReleaseVersion.h
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes_s.h
old mode 100755
new mode 100644
index 48703d1..6e742c7
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes_s.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes_s.h
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxtypes_s.h
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/build_vc.pl b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/build_vc.pl
index 649e74c..6a206c0 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/build_vc.pl
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/build_vc.pl
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 #!/usr/bin/perl
 #
 # 
@@ -6,7 +22,6 @@
 # Revision:   12290
 # Date:       Wednesday, April 9, 2008
 # 
-# (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 # 
 # 
 #
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM.c
old mode 100755
new mode 100644
index e572a89..e8dbf41
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_Bitstream.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_Bitstream.c
old mode 100755
new mode 100644
index 9ef9319..99f53ca
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_Bitstream.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_Bitstream.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM_Bitstream.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_IDCTTable.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_IDCTTable.c
old mode 100755
new mode 100644
index 3f5e279..85d4c67
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_IDCTTable.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_IDCTTable.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM_IDCTTable.c
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *   
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_MaskTable.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_MaskTable.c
old mode 100755
new mode 100644
index 09f88c3..f169a16
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_MaskTable.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_MaskTable.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVC.h
old mode 100755
new mode 100644
index 35b510b..1d37a5d
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVC.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVC.h
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVCCOMM_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVCCOMM_s.h
old mode 100755
new mode 100644
index 32a0166..cfc2a3b
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVCCOMM_s.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVCCOMM_s.h
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCCOMM_s.h
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -69,4 +83,4 @@
         
     ENDIF ;// ARMACCOMM_S_H
 
- END
\ No newline at end of file
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC_s.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
index 5c5b7d8..3d6b669 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCCOMM_ExpandFrame_I_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -233,4 +247,4 @@
     
  
             
-    END
\ No newline at end of file
+    END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/api/armVCM4P10_CAVLCTables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/api/armVCM4P10_CAVLCTables.h
old mode 100755
new mode 100644
index 547a2d9..7dde9a7
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/api/armVCM4P10_CAVLCTables.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/api/armVCM4P10_CAVLCTables.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  * 
  * 
@@ -6,7 +22,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
index 4f0892d..5f3eb9b 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_Average_4x_Align_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -219,4 +233,4 @@
     ENDIF
     
     END
-    
\ No newline at end of file
+    
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_CAVLCTables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_CAVLCTables.c
old mode 100755
new mode 100644
index 137495d..bb4bd9e
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_CAVLCTables.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_CAVLCTables.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
index 4c3a77c..e3813d3 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_DeblockingChroma_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
index 0afe4fd..bcc01dd 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_DeblockingLuma_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
index 10a89e9..6e3a0d5 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_DecodeCoeffsToPair_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DequantTables_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DequantTables_s.s
index 2761600..dce8c89 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DequantTables_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DequantTables_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_DequantTables_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -120,4 +134,4 @@
 
                            
     
-         END
\ No newline at end of file
+         END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
index 6e912d7..20b3e22 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_Align_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
index d275891..1415beb 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -146,4 +160,4 @@
     ENDIF
 
     END
-    
\ No newline at end of file
+    
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
index 4e5a39d..f5a7326 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -175,4 +189,4 @@
     ENDIF
     
     END
-    
\ No newline at end of file
+    
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
index d1684cb..4d86782 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
index 7bc091f..3bc9534 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
index babe8ad..ea1c345 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
index 89c90aa..5414d47 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
index 0f0ec78..afb9565 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_Interpolate_Chroma_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   9641
 ;// Date:       Thursday, February 7, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_QuantTables_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_QuantTables_s.s
index 7e2642b..8cd33a4 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_QuantTables_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_QuantTables_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_QuantTables_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;// Description:
@@ -71,4 +85,4 @@
          
          
          END
-         
\ No newline at end of file
+         
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
index ee9c339..9e16e49 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_TransformResidual4x4_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -183,4 +197,4 @@
         
     ENDIF                                                           ;//CortexA8            
             
-    END
\ No newline at end of file
+    END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
index 4c52e22..a24c7d5 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P10_UnpackBlock4x4_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -89,4 +103,4 @@
     
     
     END
-    
\ No newline at end of file
+    
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
old mode 100755
new mode 100644
index 40d4d5e..0a6448d
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
old mode 100755
new mode 100644
index 619365f..7b89be7
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
old mode 100755
new mode 100644
index 4e871bf..950f348
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
old mode 100755
new mode 100644
index b29e576..5e78b4c
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
index 485a488..4787982 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
index 4606197..a099dcb 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
index 18e6c1d..bf2152c 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
index 0c3f4f2..5678670 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
index e6fbb34..d2a134e 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
old mode 100755
new mode 100644
index 3ce41be..c6b3f41
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_InterpolateChroma.c
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
index 942ebc6..9f8f69e 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_InterpolateLuma_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
index 3a60705..1ff418f 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_PredictIntraChroma_8x8_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
index e9c0eee..de331f4 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_PredictIntra_16x16_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
index 39eb8a4..b5780ef 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_PredictIntra_4x4_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
index e394339..5981795 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_TransformDequantChromaDCFromPair_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
index 2529959..d8c2431 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P10_TransformDequantLumaDCFromPair_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -261,4 +275,4 @@
     ENDIF                                                           ;//ARM1136JS  
     
 
-    END
\ No newline at end of file
+    END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S
index aca2df4..46e0018 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S
index b9ee221..ca64a02 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S
index 47f3d44..193bc5e 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
index bcc6b6b..8e0db37 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S
index 5bc7875..6febf2f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S
@@ -1,5 +1,19 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S
index 37bc69b..7206d76 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S
index fe92201..e41d662 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S
index 544abe8..c8f5cda 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S
index a330972..f5868c0 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S
index 991c33f..065995d 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S
index 40e141b..1e2d16b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S
index 955846f..c7def2a 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S
index 8599cab..2f4293f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_QuantTables_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_QuantTables_s.S
index f5d6d1f..f4e6010 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_QuantTables_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_QuantTables_s.S
@@ -1,5 +1,19 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S
index c24d717..d4cedb5 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S
index c552f8d..1652dc6 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S
index ba61059..90b0947 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S
index bc0f7fa..4a74594 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S
index 79ba538..f20fb78 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S
index dcdddbe..003526e 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S
index 9755899..7ddc42e 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S
index 66cc32e..f71aceb 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S
index 76c3d7d..000fbeb 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S
index a896a3a..4e2cff6 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S
index 3944f53..c71c93b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S
@@ -1,5 +1,19 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S
index 6646b7f..cd5d356 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S
index 7ba3bd6..5570892 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S
index 640f096..5b6eee0 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S
@@ -1,5 +1,20 @@
 /*
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
+/*
  *
  */
 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
old mode 100755
new mode 100644
index 74b5505..6cbc5ff
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_Huff_Tables_VLC.h
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
old mode 100755
new mode 100644
index e95203a..0d64a68
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_ZigZag_Tables.h
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Clip8_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Clip8_s.s
index 95fe6d2..2f830fc 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Clip8_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Clip8_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ; /**
 ; * 
 ; * File Name:  armVCM4P2_Clip8_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   12290
 ; * Date:       Wednesday, April 9, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
index e4a7f33..016e65b 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   12290
 ; * Date:       Wednesday, April 9, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
old mode 100755
new mode 100644
index 38af975..5a77832
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
  /**
  * 
  * File Name:  armVCM4P2_Huff_Tables_VLC.c
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Lookup_Tables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
old mode 100755
new mode 100644
index 6948f80..e915d3c
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
  /**
  * 
  * File Name:  armVCM4P2_Lookup_Tables.c
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_SetPredDir_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
index 44f2460..bf3f363 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  armVCM4P2_SetPredDir_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
old mode 100755
new mode 100644
index 21fa715..719b434
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_Zigzag_Tables.c
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
old mode 100755
new mode 100644
index 796ad6e..95346ad
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DecodeBlockCoef_Inter.c
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
old mode 100755
new mode 100644
index b28657c..91ec5d2
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DecodeBlockCoef_Intra.c
@@ -5,7 +21,6 @@
  * Revision:   12290
  * Date:       Wednesday, April 9, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
index cc16f5a..08e9538 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ; **********
 ; * 
 ; * File Name:  omxVCM4P2_DecodePadMV_PVOP_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   12290
 ; * Date:       Wednesday, April 9, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
index 7208c21..636dfe4 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  omxVCM4P2_DecodeVLCZigzag_Inter_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   12290
 ; * Date:       Wednesday, April 9, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
index 9a37ec9..15cc5b4 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   12290
 ; * Date:       Wednesday, April 9, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
index 778aaf2..e9fed80 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   12290
 ; * Date:       Wednesday, April 9, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
index caf7121..9344120 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P2_FindMVpred_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
@@ -191,4 +205,4 @@
         M_END
     ENDIF ;// ARM1136JS :LOR: CortexA8
     
-    END
\ No newline at end of file
+    END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
index b5e3d0d..01b925e 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P2_IDCT8x8blk_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
index dd00df5..3c1aec3 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
@@ -1,11 +1,25 @@
 ;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
+;//
 ;// 
 ;// File Name:  omxVCM4P2_MCReconBlock_s.s
 ;// OpenMAX DL: v1.0.2
 ;// Revision:   12290
 ;// Date:       Wednesday, April 9, 2008
 ;// 
-;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ;// 
 ;// 
 ;//
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
index a73f64a..6b4eb28 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ; **********
 ; * 
 ; * File Name:  omxVCM4P2_PredictReconCoefIntra_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   12290
 ; * Date:       Wednesday, April 9, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
index bd0ad1f..744571f 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  omxVCM4P2_QuantInvInter_I_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   12290
 ; * Date:       Wednesday, April 9, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
index e00591f..61a7fd4 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
@@ -1,3 +1,18 @@
+;//
+;// Copyright (C) 2007-2008 ARM Limited
+;//
+;// 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.
+;//
 ;/**
 ; * 
 ; * File Name:  omxVCM4P2_QuantInvIntra_I_s.s
@@ -5,7 +20,6 @@
 ; * Revision:   12290
 ; * Date:       Wednesday, April 9, 2008
 ; * 
-; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 ; * 
 ; * 
 ; *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/src/armVC_Version.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/src/armVC_Version.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
index 2ed86a4..fbb97e2 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *   
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Bitstream.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Bitstream.h
index 4f9bc3b..576b66d 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Bitstream.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Bitstream.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM_Bitstream.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armOMX.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armOMX.h
index f629f72..e7c0c26 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armOMX.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armOMX.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* 
  * 
  * File Name:  armOMX_ReleaseVersion.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/build_vc.pl b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/build_vc.pl
index f0b43e0..e59cded 100755
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/build_vc.pl
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/build_vc.pl
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 #!/usr/bin/perl
 #
 # 
@@ -6,7 +22,6 @@
 # Revision:   9641
 # Date:       Thursday, February 7, 2008
 # 
-# (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
 # 
 # 
 #
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM.c
index e572a89..e8dbf41 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM_Bitstream.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM_Bitstream.c
index 9ef9319..99f53ca 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM_Bitstream.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM_Bitstream.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armCOMM_Bitstream.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/armVC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/armVC.h
index 7fa7716..6dbe8b6 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/armVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/armVC.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVC.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_Average.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_Average.c
index 1e51077..b7b37bf 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_Average.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_Average.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCCOMM_Average.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_SAD.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_SAD.c
index d41ac9a..05b96dc 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_SAD.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_SAD.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCCOMM_SAD.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_16x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_16x.c
index 6d1447e..175bca8 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_16x.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_16x.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCCOMM_Average_16x.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_8x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_8x.c
index 17b1326..2c14f43 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_8x.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_8x.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCCOMM_Average_8x.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock.c
index e559adf..a1f5240 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCCOMM_ComputeTextureErrorBlock.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock_SAD.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock_SAD.c
index c4731aa..a7f48c9 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock_SAD.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock_SAD.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCCOMM_ComputeTextureErrorBlock_SAD.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy16x16.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy16x16.c
index 4857024..8e467a4 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy16x16.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy16x16.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCCOMM_Copy16x16.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy8x8.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy8x8.c
index a4f9dde..3f5969b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy8x8.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy8x8.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCCOMM_Copy8x8.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ExpandFrame_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ExpandFrame_I.c
index 9536df7..5379fd0 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ExpandFrame_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ExpandFrame_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCCOMM_ExpandFrame_I.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_LimitMVToRect.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_LimitMVToRect.c
index af04582..9ba9093 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_LimitMVToRect.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_LimitMVToRect.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCCOMM_LimitMVToRect.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_16x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_16x.c
index 0f0cedb..83dbbd0 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_16x.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_16x.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCCOMM_SAD_16x.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_8x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_8x.c
index 1421d99..7bfd1ec 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_8x.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_8x.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCCOMM_SAD_8x.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/api/armVCM4P10_CAVLCTables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/api/armVCM4P10_CAVLCTables.h
index 8d18a8f..37241ca 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/api/armVCM4P10_CAVLCTables.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/api/armVCM4P10_CAVLCTables.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  * 
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CAVLCTables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CAVLCTables.c
index f4e36ad..c4a3074 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CAVLCTables.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CAVLCTables.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CompareMotionCostToMV.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CompareMotionCostToMV.c
index e4bedc2..6611a37 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CompareMotionCostToMV.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CompareMotionCostToMV.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P10_CompareMotionCostToMV.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DeBlockPixel.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DeBlockPixel.c
index f4fb1d9..c6da8ab 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DeBlockPixel.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DeBlockPixel.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair.c
index 7616add..831d53b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DequantTables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DequantTables.c
index d9c2541..ad6cef3 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DequantTables.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DequantTables.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_FwdTransformResidual4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_FwdTransformResidual4x4.c
index 93d54c3..17d6c0f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_FwdTransformResidual4x4.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_FwdTransformResidual4x4.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfDiag_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfDiag_Luma.c
index 8732f4f..ce9df49 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfDiag_Luma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfDiag_Luma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P10_InterpolateHalfDiag_Luma.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfHor_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfHor_Luma.c
index 89c0079..15462b2 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfHor_Luma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfHor_Luma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P10_InterpolateHalfHor_Luma.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfVer_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfVer_Luma.c
index f7ecfc5..e8adf45 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfVer_Luma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfVer_Luma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P10_InterpolateHalfVer_Luma.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Chroma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Chroma.c
index 1507d23..26730f8 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Chroma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Chroma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P10_Interpolate_Chroma.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Luma.c
index 89978dd..538d62e 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Luma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Luma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P10_Interpolate_Luma.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_PredictIntraDC4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_PredictIntraDC4x4.c
index b713073..a200d55 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_PredictIntraDC4x4.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_PredictIntraDC4x4.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_QuantTables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_QuantTables.c
index f0b5bb0..c01d4f6 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_QuantTables.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_QuantTables.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_SADQuar.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_SADQuar.c
index a41e04b..6ef8af5 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_SADQuar.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_SADQuar.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P10_SADQuar.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_TransformResidual4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_TransformResidual4x4.c
index f9f756a..6c53731 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_TransformResidual4x4.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_TransformResidual4x4.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock2x2.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock2x2.c
index dda49f6..fb004e5 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock2x2.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock2x2.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  * 
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock4x4.c
index 3c0dcbd..b40c933 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock4x4.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock4x4.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_Average_4x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_Average_4x.c
index ac0d523..638605e 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_Average_4x.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_Average_4x.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_Average_4x.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Half.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Half.c
index c490e10..6cfdb64 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Half.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Half.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_BlockMatch_Half.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Integer.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Integer.c
index f7764e1..050200f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Integer.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Integer.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_BlockMatch_Integer.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Quarter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Quarter.c
index 513ee25..f450d2c 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Quarter.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Quarter.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_BlockMatch_Quarter.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
index a07b1bb..9aecf3f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
index 1f3a646..a159631 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
index 830ddc7..f931eeb 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
index 7e83d1e..e8ab819 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd.c
index ed5a158..8a022ba 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c
index 75edee2..4f34a96 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c
index 10b2592..70b0e87 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c
index 30a37da..19294f8 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c
index 8733427..53e232a 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_GetVLCInfo.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_GetVLCInfo.c
index 81c59d6..c80552a 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_GetVLCInfo.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_GetVLCInfo.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_GetVLCInfo.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
index 8824de2..18824d8 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_InterpolateChroma.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfHor_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfHor_Luma.c
index ef0befa..26c8208 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfHor_Luma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfHor_Luma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_InterpolateHalfHor_Luma.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfVer_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfVer_Luma.c
index 3560ff8..96c186b 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfVer_Luma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfVer_Luma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_InterpolateHalfVer_Luma.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateLuma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateLuma.c
index d233735..e2a8163 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateLuma.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateLuma.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_InterpolateLuma.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_ChromaDC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_ChromaDC.c
index 92ba031..869e768 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_ChromaDC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_ChromaDC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_InvTransformDequant_ChromaDC.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_LumaDC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_LumaDC.c
index a3b1200..75f15cf 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_LumaDC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_LumaDC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_InvTransformDequant_LumaDC.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformResidualAndAdd.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformResidualAndAdd.c
index 3303997..e3e4519 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformResidualAndAdd.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformResidualAndAdd.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_InvTransformResidualAndAdd.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEGetBufSize.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEGetBufSize.c
index 8c3a5c3..7a245e1 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEGetBufSize.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEGetBufSize.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_MEGetBufSize.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEInit.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEInit.c
index 58ecc88..e463353 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEInit.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEInit.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_MEInit.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c
index 33dbf3f..5264394 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**                                                                            x
  * 
  * File Name:  omxVCM4P10_MotionEstimationMB.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8.c
index d6ca783..e850771 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16.c
index c90cb4c..ec44526 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4.c
index 3fa8212..44c25f6 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_16x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_16x.c
index c8114ee..140a785 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_16x.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_16x.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_SADQuar_16x.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_4x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_4x.c
index 4b330ba..4b60d34 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_4x.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_4x.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_SADQuar_4x.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_8x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_8x.c
index c9e9c24..6c8cdf3 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_8x.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_8x.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_SADQuar_8x.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SAD_4x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SAD_4x.c
index 927c454..e22d8dd 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SAD_4x.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SAD_4x.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_SAD_4x.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SATD_4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SATD_4x4.c
index a91ae66..6f74499 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SATD_4x4.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SATD_4x4.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_SATD_4x4.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c
index 23a5662..f184d7c 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_SubAndTransformQDQResidual.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair.c
index 9ad0e81..dd9f5a7 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair.c
index 16c8be1..d333d49 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /* ----------------------------------------------------------------
  *
  * 
@@ -6,7 +22,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_ChromaDC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_ChromaDC.c
index b5544dd..1b6a3d0 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_ChromaDC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_ChromaDC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_TransformQuant_ChromaDC.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_LumaDC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_LumaDC.c
index 2ccf7f0..ea99a2d 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_LumaDC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_LumaDC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P10_TransformQuant_LumaDC.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_DCT_Table.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_DCT_Table.h
index 3255b61..a72da13 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_DCT_Table.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_DCT_Table.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_DCT_Table.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
index 92ecc05..a88bdbc 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_Huff_Tables_VLC.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
index c75ed89..90c163f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_ZigZag_Tables.h
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_ACDCPredict.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_ACDCPredict.c
index b6a396a..c993f73 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_ACDCPredict.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_ACDCPredict.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_ACDCPredict.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Half.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Half.c
index 1b69a33..4ffda10 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Half.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Half.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_BlockMatch_Half.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Integer.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Integer.c
index 77fe358..2b05660 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Integer.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Integer.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_BlockMatch_Integer.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CheckVLCEscapeMode.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CheckVLCEscapeMode.c
index 94e8639..5e510e7 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CheckVLCEscapeMode.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CheckVLCEscapeMode.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_CheckVLCEscapeMode.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CompareMV.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CompareMV.c
index 3b8845e..3b621a3 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CompareMV.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CompareMV.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_CompareMV.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DCT_Table.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DCT_Table.c
index a6f713e..7d055d9 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DCT_Table.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DCT_Table.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
  /**
  * 
  * File Name:  armVCM4P2_DCT_Table.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_intra.c
index a2572e0..a5aa198 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_intra.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_intra.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_DecodeVLCZigzag_intra.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_EncodeVLCZigzag_intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_EncodeVLCZigzag_intra.c
index cd6b56d..b61c547 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_EncodeVLCZigzag_intra.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_EncodeVLCZigzag_intra.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_EncodeVLCZigzag_intra.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLCBuffer.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLCBuffer.c
index 93c9504..aeb7714 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLCBuffer.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLCBuffer.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_FillVLCBuffer.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLDBuffer.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLDBuffer.c
index 1712c3a..f09f5d5 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLDBuffer.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLDBuffer.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_FillVLDBuffer.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_GetVLCBits.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_GetVLCBits.c
index 953f597..8eb1411 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_GetVLCBits.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_GetVLCBits.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_GetVLCBits.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
index cd7e9e4..b101d48 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
  /**
  * 
  * File Name:  armVCM4P2_Huff_Tables_VLC.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_PutVLCBits.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_PutVLCBits.c
index ca9efec..21d5494 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_PutVLCBits.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_PutVLCBits.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_PutVLCBits.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_SetPredDir.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_SetPredDir.c
index a9cd008..61d44d4 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_SetPredDir.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_SetPredDir.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  armVCM4P2_SetPredDir.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
index a247c69..bcfc0ef 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
  /**
  * 
  * File Name:  armVCM4P2_Zigzag_Tables.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_16x16.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_16x16.c
index dcd3ce1..f23c533 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_16x16.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_16x16.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_BlockMatch_Half_16x16.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * 
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_8x8.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_8x8.c
index 6996e6d..83da79f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_8x8.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_8x8.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_BlockMatch_Half_8x8.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_16x16.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_16x16.c
index e714ef1..e224016 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_16x16.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_16x16.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_BlockMatch_Integer_16x16.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_8x8.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_8x8.c
index 607e64c..73a99bd 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_8x8.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_8x8.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_BlockMatch_Integer_8x8.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DCT8x8blk.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DCT8x8blk.c
index a077ac8..c73e24a 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DCT8x8blk.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DCT8x8blk.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DCT8x8blk.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
index 51f7bab..9c9a7f6 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DecodeBlockCoef_Inter.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
index a0b2376..970da6c 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DecodeBlockCoef_Intra.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP.c
index 7e159b7..ae2c220 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DecodePadMV_PVOP.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter.c
index 88a8d04..2d3cf6e 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DecodeVLCZigzag_Inter.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c
index 96593d1..6dddaf0 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c
index 95e00d7..9c76ed1 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeMV.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeMV.c
index def2b6d..c04a236 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeMV.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeMV.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_EncodeMV.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_Inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_Inter.c
index b6c73ea..2158f88 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_Inter.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_Inter.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_EncodeVLCZigzag_Inter.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c
index d047942..63b6d97 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c
index c57acd2..7bdda19 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_FindMVpred.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_FindMVpred.c
index a0cff48..054b486 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_FindMVpred.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_FindMVpred.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_FindMVpred.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_IDCT8x8blk.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_IDCT8x8blk.c
index 1886d92..c512458 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_IDCT8x8blk.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_IDCT8x8blk.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_IDCT8x8blk.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MCReconBlock.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MCReconBlock.c
index 7b3faee..33f0cf5 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MCReconBlock.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MCReconBlock.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_MCReconBlock.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  * Description:
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEGetBufSize.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEGetBufSize.c
index a8e51da..dda852e 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEGetBufSize.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEGetBufSize.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_MEGetBufSize.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEInit.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEInit.c
index 419e71a..59c57c2 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEInit.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEInit.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_MEInit.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MotionEstimationMB.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MotionEstimationMB.c
index 9549050..f9bb297 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MotionEstimationMB.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MotionEstimationMB.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_MotionEstimationMB.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra.c
index 1613f47..e091f31 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
  /**
  * 
  * File Name:  omxVCM4P2_PredictReconCoefIntra.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInter_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInter_I.c
index 5964f73..9055b66 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInter_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInter_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_QuantInter_I.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantIntra_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantIntra_I.c
index a10da68..795b802 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantIntra_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantIntra_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_QuantIntra_I.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvInter_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvInter_I.c
index 6e0de5c..189e244 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvInter_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvInter_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_QuantInvInter_I.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I.c
index a946d7b..2f24cc7 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_QuantInvIntra_I.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_inter.c
index 6e0c59b..9615a77 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_inter.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_inter.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_TransRecBlockCoef_inter.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_intra.c
index dd444f9..4923e3f 100644
--- a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_intra.c
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_intra.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2007-2008 ARM Limited
+ *
+ * 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.
+ *
+ */
 /**
  * 
  * File Name:  omxVCM4P2_TransRecBlockCoef_intra.c
@@ -5,7 +21,6 @@
  * Revision:   9641
  * Date:       Thursday, February 7, 2008
  * 
- * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
  * 
  * 
  *
diff --git a/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c b/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c b/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
index 524a3f0..a073dcb 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
+++ b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
@@ -36,6 +36,7 @@
     1. Include headers
 ------------------------------------------------------------------------------*/
 #include <stdlib.h>
+#include <string.h>
 #include "basetype.h"
 #include "h264bsd_container.h"
 #include "H264SwDecApi.h"
diff --git a/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c b/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cfg.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cfg.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_container.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_container.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.c
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.h
old mode 100755
new mode 100644
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index b8084ae..6322dc2 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -345,9 +345,15 @@
             }
 
             uint8_t channel_mapping[kMaxChannels] = {0};
-            memcpy(&channel_mapping,
-                   kDefaultOpusChannelLayout,
-                   kMaxChannelsWithDefaultLayout);
+            if (mHeader->channels <= kMaxChannelsWithDefaultLayout) {
+                memcpy(&channel_mapping,
+                       kDefaultOpusChannelLayout,
+                       kMaxChannelsWithDefaultLayout);
+            } else {
+                memcpy(&channel_mapping,
+                       mHeader->stream_map,
+                       mHeader->channels);
+            }
 
             int status = OPUS_INVALID_STATE;
             mDecoder = opus_multistream_decoder_create(kRate,
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 6474906..21da707 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -107,6 +107,7 @@
     if (!runningInEmulator()) {
         switch (mColorFormat) {
             case OMX_COLOR_FormatYUV420Planar:
+            case OMX_COLOR_FormatYUV420SemiPlanar:
             case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
             {
                 halFormat = HAL_PIXEL_FORMAT_YV12;
@@ -255,7 +256,8 @@
             dst_u += dst_c_stride;
             dst_v += dst_c_stride;
         }
-    } else if (mColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
+    } else if (mColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
+            || mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
         const uint8_t *src_y = (const uint8_t *)data;
         const uint8_t *src_uv = (const uint8_t *)data
                 + mWidth * (mHeight - mCropTop / 2);
diff --git a/media/libstagefright/data/media_codecs_google_audio.xml b/media/libstagefright/data/media_codecs_google_audio.xml
index f599004..a06684b 100644
--- a/media/libstagefright/data/media_codecs_google_audio.xml
+++ b/media/libstagefright/data/media_codecs_google_audio.xml
@@ -48,7 +48,7 @@
         </MediaCodec>
         <MediaCodec name="OMX.google.vorbis.decoder" type="audio/vorbis">
             <Limit name="channel-count" max="8" />
-            <Limit name="sample-rate" ranges="8000,11025,12000,16000,22050,24000,32000,44100,48000,96000" />
+            <Limit name="sample-rate" ranges="8000-96000" />
             <Limit name="bitrate" range="32000-500000" />
         </MediaCodec>
         <MediaCodec name="OMX.google.opus.decoder" type="audio/opus">
@@ -65,7 +65,8 @@
     <Encoders>
         <MediaCodec name="OMX.google.aac.encoder" type="audio/mp4a-latm">
             <Limit name="channel-count" max="6" />
-            <Limit name="sample-rate" ranges="11025,12000,16000,22050,24000,32000,44100,48000" />
+            <Limit name="sample-rate" ranges="8000,11025,12000,16000,22050,24000,32000,44100,48000" />
+            <!-- also may support 64000, 88200  and 96000 Hz -->
             <Limit name="bitrate" range="8000-960000" />
         </MediaCodec>
         <MediaCodec name="OMX.google.amrnb.encoder" type="audio/3gpp">
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index 1cbef39..7e9fa18 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -73,7 +73,7 @@
     <Encoders>
         <MediaCodec name="OMX.google.h263.encoder" type="video/3gpp">
             <!-- profiles and levels:  ProfileBaseline : Level45 -->
-            <Limit name="size" min="16x16" max="176x144" />
+            <Limit name="size" min="176x144" max="176x144" />
             <Limit name="alignment" value="16x16" />
             <Limit name="bitrate" range="1-128000" />
         </MediaCodec>
diff --git a/media/libstagefright/data/media_codecs_google_video_le.xml b/media/libstagefright/data/media_codecs_google_video_le.xml
new file mode 100644
index 0000000..034a038
--- /dev/null
+++ b/media/libstagefright/data/media_codecs_google_video_le.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- 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.
+-->
+
+<Included>
+    <Decoders>
+        <MediaCodec name="OMX.google.mpeg4.decoder" type="video/mp4v-es">
+            <!-- profiles and levels:  ProfileSimple : Level3 -->
+            <Limit name="size" min="2x2" max="352x288" />
+            <Limit name="alignment" value="2x2" />
+            <Limit name="block-size" value="16x16" />
+            <Limit name="blocks-per-second" range="12-11880" />
+            <Limit name="bitrate" range="1-384000" />
+            <Feature name="adaptive-playback" />
+        </MediaCodec>
+        <MediaCodec name="OMX.google.h263.decoder" type="video/3gpp">
+            <!-- profiles and levels:  ProfileBaseline : Level30, ProfileBaseline : Level45
+                    ProfileISWV2 : Level30, ProfileISWV2 : Level45 -->
+            <Limit name="size" min="2x2" max="352x288" />
+            <Limit name="alignment" value="2x2" />
+            <Limit name="bitrate" range="1-384000" />
+            <Feature name="adaptive-playback" />
+        </MediaCodec>
+        <MediaCodec name="OMX.google.h264.decoder" type="video/avc">
+            <!-- profiles and levels:  ProfileBaseline : Level51 -->
+            <Limit name="size" min="2x2" max="2048x2048" />
+            <Limit name="alignment" value="2x2" />
+            <Limit name="block-size" value="16x16" />
+            <Limit name="block-count" range="1-8160" />
+            <Limit name="blocks-per-second" range="1-489600" />
+            <Limit name="bitrate" range="1-40000000" />
+            <Feature name="adaptive-playback" />
+        </MediaCodec>
+        <MediaCodec name="OMX.google.hevc.decoder" type="video/hevc">
+            <!-- profiles and levels:  ProfileMain : MainTierLevel51 -->
+            <Limit name="size" min="2x2" max="1280x1280" />
+            <Limit name="alignment" value="2x2" />
+            <Limit name="block-size" value="8x8" />
+            <Limit name="block-count" range="1-139264" />
+            <Limit name="blocks-per-second" range="1-432000" />
+            <Limit name="bitrate" range="1-5000000" />
+            <Feature name="adaptive-playback" />
+        </MediaCodec>
+        <MediaCodec name="OMX.google.vp8.decoder" type="video/x-vnd.on2.vp8">
+            <Limit name="size" min="2x2" max="2048x2048" />
+            <Limit name="alignment" value="2x2" />
+            <Limit name="block-size" value="16x16" />
+            <Limit name="block-count" range="1-8160" />
+            <Limit name="blocks-per-second" range="1-500000" />
+            <Limit name="bitrate" range="1-40000000" />
+            <Feature name="adaptive-playback" />
+        </MediaCodec>
+        <MediaCodec name="OMX.google.vp9.decoder" type="video/x-vnd.on2.vp9">
+            <Limit name="size" min="2x2" max="1280x1280" />
+            <Limit name="alignment" value="2x2" />
+            <Limit name="block-size" value="16x16" />
+            <Limit name="block-count" range="1-3600" />
+            <Limit name="blocks-per-second" range="1-108000" />
+            <Limit name="bitrate" range="1-5000000" />
+            <Feature name="adaptive-playback" />
+        </MediaCodec>
+    </Decoders>
+
+    <Encoders>
+        <MediaCodec name="OMX.google.h263.encoder" type="video/3gpp">
+            <!-- profiles and levels:  ProfileBaseline : Level45 -->
+            <Limit name="size" min="176x144" max="176x144" />
+            <Limit name="alignment" value="16x16" />
+            <Limit name="bitrate" range="1-128000" />
+        </MediaCodec>
+        <MediaCodec name="OMX.google.h264.encoder" type="video/avc">
+            <!-- profiles and levels:  ProfileBaseline : Level2 -->
+            <Limit name="size" min="16x16" max="896x896" />
+            <Limit name="alignment" value="16x16" />
+            <Limit name="block-size" value="16x16" />
+            <Limit name="blocks-per-second" range="1-11880" />
+            <Limit name="bitrate" range="1-2000000" />
+        </MediaCodec>
+        <MediaCodec name="OMX.google.mpeg4.encoder" type="video/mp4v-es">
+            <!-- profiles and levels:  ProfileCore : Level2 -->
+            <Limit name="size" min="16x16" max="176x144" />
+            <Limit name="alignment" value="16x16" />
+            <Limit name="block-size" value="16x16" />
+            <Limit name="blocks-per-second" range="12-1485" />
+            <Limit name="bitrate" range="1-64000" />
+        </MediaCodec>
+        <MediaCodec name="OMX.google.vp8.encoder" type="video/x-vnd.on2.vp8">
+            <!-- profiles and levels:  ProfileMain : Level_Version0-3 -->
+            <Limit name="size" min="2x2" max="1280x1280" />
+            <Limit name="alignment" value="2x2" />
+            <Limit name="block-count" range="1-3600" />
+            <Limit name="bitrate" range="1-20000000" />
+            <Feature name="bitrate-modes" value="VBR,CBR" />
+        </MediaCodec>
+    </Encoders>
+</Included>
diff --git a/media/libstagefright/filters/Android.mk b/media/libstagefright/filters/Android.mk
index 5e895e1..36ab444 100644
--- a/media/libstagefright/filters/Android.mk
+++ b/media/libstagefright/filters/Android.mk
@@ -1,8 +1,6 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_NDK_STL_VARIANT := stlport_static
-
 LOCAL_SRC_FILES := \
         ColorConvert.cpp          \
         GraphicBufferListener.cpp \
@@ -15,9 +13,6 @@
         ZeroFilter.cpp
 
 LOCAL_C_INCLUDES := \
-        $(TOP)/bionic \
-        $(TOP)/bionic/libstdc++/include \
-        $(TOP)/external/stlport/stlport \
         $(TOP)/frameworks/native/include/media/openmax \
         $(TOP)/frameworks/rs/cpp \
         $(TOP)/frameworks/rs \
diff --git a/media/libstagefright/filters/GraphicBufferListener.cpp b/media/libstagefright/filters/GraphicBufferListener.cpp
index e493137..66374ba 100644
--- a/media/libstagefright/filters/GraphicBufferListener.cpp
+++ b/media/libstagefright/filters/GraphicBufferListener.cpp
@@ -21,6 +21,8 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaErrors.h>
 
+#include <gui/BufferItem.h>
+
 #include "GraphicBufferListener.h"
 
 namespace android {
@@ -60,7 +62,7 @@
     return OK;
 }
 
-void GraphicBufferListener::onFrameAvailable() {
+void GraphicBufferListener::onFrameAvailable(const BufferItem& /* item */) {
     ALOGV("onFrameAvailable() called");
 
     {
@@ -83,8 +85,8 @@
     // nothing to do
 }
 
-BufferQueue::BufferItem GraphicBufferListener::getBufferItem() {
-    BufferQueue::BufferItem item;
+BufferItem GraphicBufferListener::getBufferItem() {
+    BufferItem item;
 
     {
         Mutex::Autolock autoLock(mMutex);
@@ -124,8 +126,7 @@
     return item;
 }
 
-sp<GraphicBuffer> GraphicBufferListener::getBuffer(
-        BufferQueue::BufferItem item) {
+sp<GraphicBuffer> GraphicBufferListener::getBuffer(BufferItem item) {
     sp<GraphicBuffer> buf;
     if (item.mBuf < 0 || item.mBuf >= BufferQueue::NUM_BUFFER_SLOTS) {
         ALOGE("getBuffer() received invalid BufferItem: mBuf==%d", item.mBuf);
@@ -138,8 +139,7 @@
     return buf;
 }
 
-status_t GraphicBufferListener::releaseBuffer(
-        BufferQueue::BufferItem item) {
+status_t GraphicBufferListener::releaseBuffer(BufferItem item) {
     if (item.mBuf < 0 || item.mBuf >= BufferQueue::NUM_BUFFER_SLOTS) {
         ALOGE("getBuffer() received invalid BufferItem: mBuf==%d", item.mBuf);
         return ERROR_OUT_OF_RANGE;
diff --git a/media/libstagefright/filters/GraphicBufferListener.h b/media/libstagefright/filters/GraphicBufferListener.h
index aefac0d..586bf65 100644
--- a/media/libstagefright/filters/GraphicBufferListener.h
+++ b/media/libstagefright/filters/GraphicBufferListener.h
@@ -31,7 +31,7 @@
             const sp<AMessage> &notify,
             size_t bufferWidth, size_t bufferHeight, size_t bufferCount);
 
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
     virtual void onBuffersReleased();
     virtual void onSidebandStreamChanged();
 
@@ -41,9 +41,9 @@
         return mProducer;
     }
 
-    BufferQueue::BufferItem getBufferItem();
-    sp<GraphicBuffer> getBuffer(BufferQueue::BufferItem item);
-    status_t releaseBuffer(BufferQueue::BufferItem item);
+    BufferItem getBufferItem();
+    sp<GraphicBuffer> getBuffer(BufferItem item);
+    status_t releaseBuffer(BufferItem item);
 
     enum {
         kWhatFrameAvailable = 'frav',
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
index c5289b6..0a09575 100644
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ b/media/libstagefright/filters/MediaFilter.cpp
@@ -31,6 +31,8 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaFilter.h>
 
+#include <gui/BufferItem.h>
+
 #include "ColorConvert.h"
 #include "GraphicBufferListener.h"
 #include "IntrinsicBlurFilter.h"
@@ -60,36 +62,36 @@
 
 void MediaFilter::initiateAllocateComponent(const sp<AMessage> &msg) {
     msg->setWhat(kWhatAllocateComponent);
-    msg->setTarget(id());
+    msg->setTarget(this);
     msg->post();
 }
 
 void MediaFilter::initiateConfigureComponent(const sp<AMessage> &msg) {
     msg->setWhat(kWhatConfigureComponent);
-    msg->setTarget(id());
+    msg->setTarget(this);
     msg->post();
 }
 
 void MediaFilter::initiateCreateInputSurface() {
-    (new AMessage(kWhatCreateInputSurface, id()))->post();
+    (new AMessage(kWhatCreateInputSurface, this))->post();
 }
 
 void MediaFilter::initiateStart() {
-    (new AMessage(kWhatStart, id()))->post();
+    (new AMessage(kWhatStart, this))->post();
 }
 
 void MediaFilter::initiateShutdown(bool keepComponentAllocated) {
-    sp<AMessage> msg = new AMessage(kWhatShutdown, id());
+    sp<AMessage> msg = new AMessage(kWhatShutdown, this);
     msg->setInt32("keepComponentAllocated", keepComponentAllocated);
     msg->post();
 }
 
 void MediaFilter::signalFlush() {
-    (new AMessage(kWhatFlush, id()))->post();
+    (new AMessage(kWhatFlush, this))->post();
 }
 
 void MediaFilter::signalResume() {
-    (new AMessage(kWhatResume, id()))->post();
+    (new AMessage(kWhatResume, this))->post();
 }
 
 // nothing to do
@@ -98,13 +100,13 @@
 }
 
 void MediaFilter::signalSetParameters(const sp<AMessage> &params) {
-    sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
+    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
     msg->setMessage("params", params);
     msg->post();
 }
 
 void MediaFilter::signalEndOfInputStream() {
-    (new AMessage(kWhatSignalEndOfInputStream, id()))->post();
+    (new AMessage(kWhatSignalEndOfInputStream, this))->post();
 }
 
 void MediaFilter::onMessageReceived(const sp<AMessage> &msg) {
@@ -208,7 +210,7 @@
 //////////////////// HELPER FUNCTIONS //////////////////////////////////////////
 
 void MediaFilter::signalProcessBuffers() {
-    (new AMessage(kWhatProcessBuffers, id()))->post();
+    (new AMessage(kWhatProcessBuffers, this))->post();
 }
 
 void MediaFilter::signalError(status_t error) {
@@ -309,7 +311,7 @@
     info->mData->meta()->clear();
     notify->setBuffer("buffer", info->mData);
 
-    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
+    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, this);
     reply->setInt32("buffer-id", info->mBufferID);
 
     notify->setMessage("reply", reply);
@@ -329,7 +331,7 @@
     notify->setInt32("flags", info->mOutputFlags);
     notify->setBuffer("buffer", info->mData);
 
-    sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, id());
+    sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this);
     reply->setInt32("buffer-id", info->mBufferID);
 
     notify->setMessage("reply", reply);
@@ -729,7 +731,7 @@
     mGraphicBufferListener = new GraphicBufferListener;
 
     sp<AMessage> notify = new AMessage();
-    notify->setTarget(id());
+    notify->setTarget(this);
     status_t err = mGraphicBufferListener->init(
             notify, mStride, mSliceHeight, kBufferCountActual);
 
@@ -749,7 +751,7 @@
 }
 
 void MediaFilter::onInputFrameAvailable() {
-    BufferQueue::BufferItem item = mGraphicBufferListener->getBufferItem();
+    BufferItem item = mGraphicBufferListener->getBufferItem();
     sp<GraphicBuffer> buf = mGraphicBufferListener->getBuffer(item);
 
     // get pointer to graphic buffer
diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/libstagefright/foundation/ADebug.cpp
new file mode 100644
index 0000000..ec4a960
--- /dev/null
+++ b/media/libstagefright/foundation/ADebug.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2014 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 <errno.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#define LOG_TAG "ADebug"
+#include <utils/Log.h>
+#include <utils/misc.h>
+
+#include <cutils/properties.h>
+
+#include <ADebug.h>
+#include <AStringUtils.h>
+#include <AUtils.h>
+
+namespace android {
+
+//static
+ADebug::Level ADebug::GetDebugLevelFromString(
+        const char *name, const char *value, ADebug::Level def) {
+    // split on ,
+    const char *next = value, *current;
+    const unsigned long maxLevel = (unsigned long)kDebugMax;
+    while (next != NULL) {
+        current = next;
+        next = strchr(current, ',');
+        if (next != NULL) {
+            ++next;  // pass ,
+        }
+
+        while (isspace(*current)) {
+            ++current;
+        }
+        // check for :
+        char *colon = strchr(current, ':');
+
+        // get level
+        char *end;
+        errno = 0;  // strtoul does not clear errno, but it can be set for any return value
+        unsigned long level = strtoul(current, &end, 10);
+        while (isspace(*end)) {
+            ++end;
+        }
+        if (errno != 0 || end == current || (end != colon && *end != '\0' && end != next)) {
+            // invalid level - skip
+            continue;
+        }
+        if (colon != NULL) {
+            // check if pattern matches
+            do {  // skip colon and spaces
+                ++colon;
+            } while (isspace(*colon));
+            size_t globLen = (next == NULL ? strlen(colon) : (next - 1 - colon));
+            while (globLen > 0 && isspace(colon[globLen - 1])) {
+                --globLen;  // trim glob
+            }
+
+            if (!AStringUtils::MatchesGlob(
+                    colon, globLen, name, strlen(name), true /* ignoreCase */)) {
+                continue;
+            }
+        }
+
+        // update debug level
+        def = (Level)min(level, maxLevel);
+    }
+    return def;
+}
+
+//static
+ADebug::Level ADebug::GetDebugLevelFromProperty(
+        const char *name, const char *propertyName, ADebug::Level def) {
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get(propertyName, value, NULL)) {
+        return GetDebugLevelFromString(name, value, def);
+    }
+    return def;
+}
+
+//static
+char *ADebug::GetDebugName(const char *name) {
+    char *debugName = strdup(name);
+    const char *terms[] = { "omx", "video", "audio" };
+    for (size_t i = 0; i < NELEM(terms) && debugName != NULL; i++) {
+        const char *term = terms[i];
+        const size_t len = strlen(term);
+        char *match = strcasestr(debugName, term);
+        if (match != NULL && (match == debugName || match[-1] == '.'
+                || match[len] == '.' || match[len] == '\0')) {
+            char *src = match + len;
+            if (match == debugName || match[-1] == '.') {
+                src += (*src == '.');  // remove trailing or double .
+            }
+            memmove(match, src, debugName + strlen(debugName) - src + 1);
+        }
+    }
+
+    return debugName;
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/foundation/AHandler.cpp b/media/libstagefright/foundation/AHandler.cpp
index bd5f7e9..7dbbe54 100644
--- a/media/libstagefright/foundation/AHandler.cpp
+++ b/media/libstagefright/foundation/AHandler.cpp
@@ -19,15 +19,23 @@
 #include <utils/Log.h>
 
 #include <media/stagefright/foundation/AHandler.h>
-
-#include <media/stagefright/foundation/ALooperRoster.h>
+#include <media/stagefright/foundation/AMessage.h>
 
 namespace android {
 
-sp<ALooper> AHandler::looper() {
-    extern ALooperRoster gLooperRoster;
+void AHandler::deliverMessage(const sp<AMessage> &msg) {
+    onMessageReceived(msg);
+    mMessageCounter++;
 
-    return gLooperRoster.findLooper(id());
+    if (mVerboseStats) {
+        uint32_t what = msg->what();
+        ssize_t idx = mMessages.indexOfKey(what);
+        if (idx < 0) {
+            mMessages.add(what, 1);
+        } else {
+            mMessages.editValueAt(idx)++;
+        }
+    }
 }
 
 }  // namespace android
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index 88b1c92..90b5f68 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -16,6 +16,9 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ALooper"
+
+#include <media/stagefright/foundation/ADebug.h>
+
 #include <utils/Log.h>
 
 #include <sys/time.h>
@@ -210,7 +213,7 @@
         mEventQueue.erase(mEventQueue.begin());
     }
 
-    gLooperRoster.deliverMessage(event.mMessage);
+    event.mMessage->deliver();
 
     // NOTE: It's important to note that at this point our "ALooper" object
     // may no longer exist (its final reference may have gone away while
@@ -220,4 +223,29 @@
     return true;
 }
 
+// to be called by AMessage::postAndAwaitResponse only
+sp<AReplyToken> ALooper::createReplyToken() {
+    return new AReplyToken(this);
+}
+
+// to be called by AMessage::postAndAwaitResponse only
+status_t ALooper::awaitResponse(const sp<AReplyToken> &replyToken, sp<AMessage> *response) {
+    // return status in case we want to handle an interrupted wait
+    Mutex::Autolock autoLock(mRepliesLock);
+    CHECK(replyToken != NULL);
+    while (!replyToken->retrieveReply(response)) {
+        mRepliesCondition.wait(mRepliesLock);
+    }
+    return OK;
+}
+
+status_t ALooper::postReply(const sp<AReplyToken> &replyToken, const sp<AMessage> &reply) {
+    Mutex::Autolock autoLock(mRepliesLock);
+    status_t err = replyToken->setReply(reply);
+    if (err == OK) {
+        mRepliesCondition.broadcast();
+    }
+    return err;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
index e0dc768..473ce1b 100644
--- a/media/libstagefright/foundation/ALooperRoster.cpp
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -17,6 +17,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ALooperRoster"
 #include <utils/Log.h>
+#include <utils/String8.h>
 
 #include "ALooperRoster.h"
 
@@ -26,9 +27,10 @@
 
 namespace android {
 
+static bool verboseStats = false;
+
 ALooperRoster::ALooperRoster()
-    : mNextHandlerID(1),
-      mNextReplyID(1) {
+    : mNextHandlerID(1) {
 }
 
 ALooper::handler_id ALooperRoster::registerHandler(
@@ -46,7 +48,7 @@
     ALooper::handler_id handlerID = mNextHandlerID++;
     mHandlers.add(handlerID, info);
 
-    handler->setID(handlerID);
+    handler->setID(handlerID, looper);
 
     return handlerID;
 }
@@ -65,7 +67,7 @@
     sp<AHandler> handler = info.mHandler.promote();
 
     if (handler != NULL) {
-        handler->setID(0);
+        handler->setID(0, NULL);
     }
 
     mHandlers.removeItemsAt(index);
@@ -97,103 +99,73 @@
     }
 }
 
-status_t ALooperRoster::postMessage(
-        const sp<AMessage> &msg, int64_t delayUs) {
-
-    sp<ALooper> looper = findLooper(msg->target());
-
-    if (looper == NULL) {
-        return -ENOENT;
+static void makeFourCC(uint32_t fourcc, char *s) {
+    s[0] = (fourcc >> 24) & 0xff;
+    if (s[0]) {
+        s[1] = (fourcc >> 16) & 0xff;
+        s[2] = (fourcc >> 8) & 0xff;
+        s[3] = fourcc & 0xff;
+        s[4] = 0;
+    } else {
+        sprintf(s, "%u", fourcc);
     }
-    looper->post(msg, delayUs);
-    return OK;
 }
 
-void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
-    sp<AHandler> handler;
-
-    {
-        Mutex::Autolock autoLock(mLock);
-
-        ssize_t index = mHandlers.indexOfKey(msg->target());
-
-        if (index < 0) {
-            ALOGW("failed to deliver message. Target handler not registered.");
-            return;
-        }
-
-        const HandlerInfo &info = mHandlers.valueAt(index);
-        handler = info.mHandler.promote();
-
-        if (handler == NULL) {
-            ALOGW("failed to deliver message. "
-                 "Target handler %d registered, but object gone.",
-                 msg->target());
-
-            mHandlers.removeItemsAt(index);
-            return;
+void ALooperRoster::dump(int fd, const Vector<String16>& args) {
+    bool clear = false;
+    bool oldVerbose = verboseStats;
+    for (size_t i = 0; i < args.size(); i++) {
+        if (args[i] == String16("-c")) {
+            clear = true;
+        } else if (args[i] == String16("-von")) {
+            verboseStats = true;
+        } else if (args[i] == String16("-voff")) {
+            verboseStats = false;
         }
     }
-
-    handler->onMessageReceived(msg);
-}
-
-sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) {
-    Mutex::Autolock autoLock(mLock);
-
-    ssize_t index = mHandlers.indexOfKey(handlerID);
-
-    if (index < 0) {
-        return NULL;
-    }
-
-    sp<ALooper> looper = mHandlers.valueAt(index).mLooper.promote();
-
-    if (looper == NULL) {
-        mHandlers.removeItemsAt(index);
-        return NULL;
-    }
-
-    return looper;
-}
-
-status_t ALooperRoster::postAndAwaitResponse(
-        const sp<AMessage> &msg, sp<AMessage> *response) {
-    sp<ALooper> looper = findLooper(msg->target());
-
-    if (looper == NULL) {
-        ALOGW("failed to post message. "
-                "Target handler %d still registered, but object gone.",
-                msg->target());
-        response->clear();
-        return -ENOENT;
+    String8 s;
+    if (verboseStats && !oldVerbose) {
+        s.append("(verbose stats collection enabled, stats will be cleared)\n");
     }
 
     Mutex::Autolock autoLock(mLock);
+    size_t n = mHandlers.size();
+    s.appendFormat(" %zu registered handlers:\n", n);
 
-    uint32_t replyID = mNextReplyID++;
-
-    msg->setInt32("replyID", replyID);
-
-    looper->post(msg, 0 /* delayUs */);
-
-    ssize_t index;
-    while ((index = mReplies.indexOfKey(replyID)) < 0) {
-        mRepliesCondition.wait(mLock);
+    for (size_t i = 0; i < n; i++) {
+        s.appendFormat("  %d: ", mHandlers.keyAt(i));
+        HandlerInfo &info = mHandlers.editValueAt(i);
+        sp<ALooper> looper = info.mLooper.promote();
+        if (looper != NULL) {
+            s.append(looper->getName());
+            sp<AHandler> handler = info.mHandler.promote();
+            if (handler != NULL) {
+                handler->mVerboseStats = verboseStats;
+                s.appendFormat(": %u messages processed", handler->mMessageCounter);
+                if (verboseStats) {
+                    for (size_t j = 0; j < handler->mMessages.size(); j++) {
+                        char fourcc[15];
+                        makeFourCC(handler->mMessages.keyAt(j), fourcc);
+                        s.appendFormat("\n    %s: %u",
+                                fourcc,
+                                handler->mMessages.valueAt(j));
+                    }
+                } else {
+                    handler->mMessages.clear();
+                }
+                if (clear || (verboseStats && !oldVerbose)) {
+                    handler->mMessageCounter = 0;
+                    handler->mMessages.clear();
+                }
+            } else {
+                s.append(": <stale handler>");
+            }
+        } else {
+            s.append("<stale>");
+        }
+        s.append("\n");
     }
-
-    *response = mReplies.valueAt(index);
-    mReplies.removeItemsAt(index);
-
-    return OK;
-}
-
-void ALooperRoster::postReply(uint32_t replyID, const sp<AMessage> &reply) {
-    Mutex::Autolock autoLock(mLock);
-
-    CHECK(mReplies.indexOfKey(replyID) < 0);
-    mReplies.add(replyID, reply);
-    mRepliesCondition.broadcast();
+    write(fd, s.string(), s.size());
 }
 
 }  // namespace android
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 795e8a6..e549ff6 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -27,6 +27,7 @@
 #include "ABuffer.h"
 #include "ADebug.h"
 #include "ALooperRoster.h"
+#include "AHandler.h"
 #include "AString.h"
 
 #include <binder/Parcel.h>
@@ -36,12 +37,29 @@
 
 extern ALooperRoster gLooperRoster;
 
-AMessage::AMessage(uint32_t what, ALooper::handler_id target)
-    : mWhat(what),
-      mTarget(target),
+status_t AReplyToken::setReply(const sp<AMessage> &reply) {
+    if (mReplied) {
+        ALOGE("trying to post a duplicate reply");
+        return -EBUSY;
+    }
+    CHECK(mReply == NULL);
+    mReply = reply;
+    mReplied = true;
+    return OK;
+}
+
+AMessage::AMessage(void)
+    : mWhat(0),
+      mTarget(0),
       mNumItems(0) {
 }
 
+AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
+    : mWhat(what),
+      mNumItems(0) {
+    setTarget(handler);
+}
+
 AMessage::~AMessage() {
     clear();
 }
@@ -54,12 +72,16 @@
     return mWhat;
 }
 
-void AMessage::setTarget(ALooper::handler_id handlerID) {
-    mTarget = handlerID;
-}
-
-ALooper::handler_id AMessage::target() const {
-    return mTarget;
+void AMessage::setTarget(const sp<const AHandler> &handler) {
+    if (handler == NULL) {
+        mTarget = 0;
+        mHandler.clear();
+        mLooper.clear();
+    } else {
+        mTarget = handler->id();
+        mHandler = handler->getHandler();
+        mLooper = handler->getLooper();
+    }
 }
 
 void AMessage::clear() {
@@ -322,33 +344,76 @@
     return true;
 }
 
-void AMessage::post(int64_t delayUs) {
-    gLooperRoster.postMessage(this, delayUs);
+void AMessage::deliver() {
+    sp<AHandler> handler = mHandler.promote();
+    if (handler == NULL) {
+        ALOGW("failed to deliver message as target handler %d is gone.", mTarget);
+        return;
+    }
+
+    handler->deliverMessage(this);
+}
+
+status_t AMessage::post(int64_t delayUs) {
+    sp<ALooper> looper = mLooper.promote();
+    if (looper == NULL) {
+        ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
+        return -ENOENT;
+    }
+
+    looper->post(this, delayUs);
+    return OK;
 }
 
 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
-    return gLooperRoster.postAndAwaitResponse(this, response);
+    sp<ALooper> looper = mLooper.promote();
+    if (looper == NULL) {
+        ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
+        return -ENOENT;
+    }
+
+    sp<AReplyToken> token = looper->createReplyToken();
+    if (token == NULL) {
+        ALOGE("failed to create reply token");
+        return -ENOMEM;
+    }
+    setObject("replyID", token);
+
+    looper->post(this, 0 /* delayUs */);
+    return looper->awaitResponse(token, response);
 }
 
-void AMessage::postReply(uint32_t replyID) {
-    gLooperRoster.postReply(replyID, this);
+status_t AMessage::postReply(const sp<AReplyToken> &replyToken) {
+    if (replyToken == NULL) {
+        ALOGW("failed to post reply to a NULL token");
+        return -ENOENT;
+    }
+    sp<ALooper> looper = replyToken->getLooper();
+    if (looper == NULL) {
+        ALOGW("failed to post reply as target looper is gone.");
+        return -ENOENT;
+    }
+    return looper->postReply(replyToken, this);
 }
 
-bool AMessage::senderAwaitsResponse(uint32_t *replyID) const {
-    int32_t tmp;
-    bool found = findInt32("replyID", &tmp);
+bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) {
+    sp<RefBase> tmp;
+    bool found = findObject("replyID", &tmp);
 
     if (!found) {
         return false;
     }
 
-    *replyID = static_cast<uint32_t>(tmp);
+    *replyToken = static_cast<AReplyToken *>(tmp.get());
+    tmp.clear();
+    setObject("replyID", tmp);
+    // TODO: delete Object instead of setting it to NULL
 
-    return true;
+    return *replyToken != NULL;
 }
 
 sp<AMessage> AMessage::dup() const {
-    sp<AMessage> msg = new AMessage(mWhat, mTarget);
+    sp<AMessage> msg = new AMessage(mWhat, mHandler.promote());
     msg->mNumItems = mNumItems;
 
 #ifdef DUMP_STATS
@@ -426,19 +491,19 @@
 
     AString tmp;
     if (isFourcc(mWhat)) {
-        tmp = StringPrintf(
+        tmp = AStringPrintf(
                 "'%c%c%c%c'",
                 (char)(mWhat >> 24),
                 (char)((mWhat >> 16) & 0xff),
                 (char)((mWhat >> 8) & 0xff),
                 (char)(mWhat & 0xff));
     } else {
-        tmp = StringPrintf("0x%08x", mWhat);
+        tmp = AStringPrintf("0x%08x", mWhat);
     }
     s.append(tmp);
 
     if (mTarget != 0) {
-        tmp = StringPrintf(", target = %d", mTarget);
+        tmp = AStringPrintf(", target = %d", mTarget);
         s.append(tmp);
     }
     s.append(") = {\n");
@@ -448,37 +513,37 @@
 
         switch (item.mType) {
             case kTypeInt32:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "int32_t %s = %d", item.mName, item.u.int32Value);
                 break;
             case kTypeInt64:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "int64_t %s = %lld", item.mName, item.u.int64Value);
                 break;
             case kTypeSize:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "size_t %s = %d", item.mName, item.u.sizeValue);
                 break;
             case kTypeFloat:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "float %s = %f", item.mName, item.u.floatValue);
                 break;
             case kTypeDouble:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "double %s = %f", item.mName, item.u.doubleValue);
                 break;
             case kTypePointer:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "void *%s = %p", item.mName, item.u.ptrValue);
                 break;
             case kTypeString:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "string %s = \"%s\"",
                         item.mName,
                         item.u.stringValue->c_str());
                 break;
             case kTypeObject:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "RefBase *%s = %p", item.mName, item.u.refValue);
                 break;
             case kTypeBuffer:
@@ -486,18 +551,18 @@
                 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
 
                 if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
-                    tmp = StringPrintf("Buffer %s = {\n", item.mName);
+                    tmp = AStringPrintf("Buffer %s = {\n", item.mName);
                     hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
                     appendIndent(&tmp, indent + 2);
                     tmp.append("}");
                 } else {
-                    tmp = StringPrintf(
+                    tmp = AStringPrintf(
                             "Buffer *%s = %p", item.mName, buffer.get());
                 }
                 break;
             }
             case kTypeMessage:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "AMessage %s = %s",
                         item.mName,
                         static_cast<AMessage *>(
@@ -505,7 +570,7 @@
                                 indent + strlen(item.mName) + 14).c_str());
                 break;
             case kTypeRect:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "Rect %s(%d, %d, %d, %d)",
                         item.mName,
                         item.u.rectValue.mLeft,
@@ -532,7 +597,8 @@
 // static
 sp<AMessage> AMessage::FromParcel(const Parcel &parcel) {
     int32_t what = parcel.readInt32();
-    sp<AMessage> msg = new AMessage(what);
+    sp<AMessage> msg = new AMessage();
+    msg->setWhat(what);
 
     msg->mNumItems = static_cast<size_t>(parcel.readInt32());
     for (size_t i = 0; i < msg->mNumItems; ++i) {
diff --git a/media/libstagefright/foundation/ANetworkSession.cpp b/media/libstagefright/foundation/ANetworkSession.cpp
index 4504c2b..b230400 100644
--- a/media/libstagefright/foundation/ANetworkSession.cpp
+++ b/media/libstagefright/foundation/ANetworkSession.cpp
@@ -187,7 +187,7 @@
         CHECK_GE(res, 0);
 
         in_addr_t addr = ntohl(localAddr.sin_addr.s_addr);
-        AString localAddrString = StringPrintf(
+        AString localAddrString = AStringPrintf(
                 "%d.%d.%d.%d",
                 (addr >> 24),
                 (addr >> 16) & 0xff,
@@ -195,7 +195,7 @@
                 addr & 0xff);
 
         addr = ntohl(remoteAddr.sin_addr.s_addr);
-        AString remoteAddrString = StringPrintf(
+        AString remoteAddrString = AStringPrintf(
                 "%d.%d.%d.%d",
                 (addr >> 24),
                 (addr >> 16) & 0xff,
@@ -301,7 +301,7 @@
                 uint32_t ip = ntohl(remoteAddr.sin_addr.s_addr);
                 notify->setString(
                         "fromAddr",
-                        StringPrintf(
+                        AStringPrintf(
                             "%u.%u.%u.%u",
                             ip >> 24,
                             (ip >> 16) & 0xff,
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index 9835ca3..b167543 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -366,7 +366,7 @@
     return err;
 }
 
-AString StringPrintf(const char *format, ...) {
+AString AStringPrintf(const char *format, ...) {
     va_list ap;
     va_start(ap, format);
 
diff --git a/media/libstagefright/foundation/AStringUtils.cpp b/media/libstagefright/foundation/AStringUtils.cpp
new file mode 100644
index 0000000..e5a846c
--- /dev/null
+++ b/media/libstagefright/foundation/AStringUtils.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 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 <string.h>
+#include <AStringUtils.h>
+
+namespace android {
+
+// static
+int AStringUtils::Compare(const char *a, const char *b, size_t len, bool ignoreCase) {
+    // this method relies on a trailing '\0' if a or b are shorter than len
+    return ignoreCase ? strncasecmp(a, b, len) : strncmp(a, b, len);
+}
+
+// static
+bool AStringUtils::MatchesGlob(
+        const char *glob, size_t globLen, const char *str, size_t strLen, bool ignoreCase) {
+    // this method does not assume a trailing '\0'
+    size_t ix = 0, globIx = 0;
+
+    // pattern must match until first '*'
+    while (globIx < globLen && glob[globIx] != '*') {
+        ++globIx;
+    }
+    if (strLen < globIx || Compare(str, glob, globIx /* len */, ignoreCase)) {
+        return false;
+    }
+    ix = globIx;
+
+    // process by * separated sections
+    while (globIx < globLen) {
+        ++globIx;
+        size_t start = globIx;
+        while (globIx < globLen && glob[globIx] != '*') {
+            ++globIx;
+        }
+        size_t len = globIx - start;
+        const char *pattern = glob + start;
+
+        if (globIx == globLen) {
+            // last pattern must match tail
+            if (ix + len > strLen) {
+                return false;
+            }
+            const char *tail = str + strLen - len;
+            return !Compare(tail, pattern, len, ignoreCase);
+        }
+        // progress after first occurrence of pattern
+        while (ix + len <= strLen && Compare(str + ix, pattern, len, ignoreCase)) {
+            ++ix;
+        }
+        if (ix + len > strLen) {
+            return false;
+        }
+        ix += len;
+        // we will loop around as globIx < globLen
+    }
+
+    // we only get here if there were no * in the pattern
+    return ix == strLen;
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/foundation/AWakeLock.cpp b/media/libstagefright/foundation/AWakeLock.cpp
new file mode 100644
index 0000000..d9277ac
--- /dev/null
+++ b/media/libstagefright/foundation/AWakeLock.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "AWakeLock"
+#include <utils/Log.h>
+
+#include "ADebug.h"
+#include "AWakeLock.h"
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <powermanager/PowerManager.h>
+
+
+namespace android {
+
+AWakeLock::AWakeLock() :
+    mPowerManager(NULL),
+    mWakeLockToken(NULL),
+    mWakeLockCount(0),
+    mDeathRecipient(new PMDeathRecipient(this)) {}
+
+AWakeLock::~AWakeLock() {
+    if (mPowerManager != NULL) {
+        sp<IBinder> binder = IInterface::asBinder(mPowerManager);
+        binder->unlinkToDeath(mDeathRecipient);
+    }
+    clearPowerManager();
+}
+
+bool AWakeLock::acquire() {
+    if (mWakeLockCount == 0) {
+        CHECK(mWakeLockToken == NULL);
+        if (mPowerManager == NULL) {
+            // use checkService() to avoid blocking if power service is not up yet
+            sp<IBinder> binder =
+                defaultServiceManager()->checkService(String16("power"));
+            if (binder == NULL) {
+                ALOGW("could not get the power manager service");
+            } else {
+                mPowerManager = interface_cast<IPowerManager>(binder);
+                binder->linkToDeath(mDeathRecipient);
+            }
+        }
+        if (mPowerManager != NULL) {
+            sp<IBinder> binder = new BBinder();
+            int64_t token = IPCThreadState::self()->clearCallingIdentity();
+            status_t status = mPowerManager->acquireWakeLock(
+                    POWERMANAGER_PARTIAL_WAKE_LOCK,
+                    binder, String16("AWakeLock"), String16("media"));
+            IPCThreadState::self()->restoreCallingIdentity(token);
+            if (status == NO_ERROR) {
+                mWakeLockToken = binder;
+                mWakeLockCount++;
+                return true;
+            }
+        }
+    } else {
+        mWakeLockCount++;
+        return true;
+    }
+    return false;
+}
+
+void AWakeLock::release(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 != NULL);
+        if (mPowerManager != NULL) {
+            int64_t token = IPCThreadState::self()->clearCallingIdentity();
+            mPowerManager->releaseWakeLock(mWakeLockToken, 0 /* flags */);
+            IPCThreadState::self()->restoreCallingIdentity(token);
+        }
+        mWakeLockToken.clear();
+    }
+}
+
+void AWakeLock::clearPowerManager() {
+    release(true);
+    mPowerManager.clear();
+}
+
+void AWakeLock::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused) {
+    if (mWakeLock != NULL) {
+        mWakeLock->clearPowerManager();
+    }
+}
+
+}  // namespace android
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index 90a6a23..08355c7 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -5,6 +5,7 @@
     AAtomizer.cpp                 \
     ABitReader.cpp                \
     ABuffer.cpp                   \
+    ADebug.cpp                    \
     AHandler.cpp                  \
     AHierarchicalStateMachine.cpp \
     ALooper.cpp                   \
@@ -12,6 +13,8 @@
     AMessage.cpp                  \
     ANetworkSession.cpp           \
     AString.cpp                   \
+    AStringUtils.cpp              \
+    AWakeLock.cpp                 \
     ParsedMessage.cpp             \
     base64.cpp                    \
     hexdump.cpp
@@ -22,7 +25,9 @@
 LOCAL_SHARED_LIBRARIES := \
         libbinder         \
         libutils          \
-        liblog
+        libcutils         \
+        liblog            \
+        libpowermanager
 
 LOCAL_CFLAGS += -Wno-multichar -Werror
 
diff --git a/media/libstagefright/http/MediaHTTP.cpp b/media/libstagefright/http/MediaHTTP.cpp
index 2d29913..bb89567 100644
--- a/media/libstagefright/http/MediaHTTP.cpp
+++ b/media/libstagefright/http/MediaHTTP.cpp
@@ -129,7 +129,7 @@
 
     *size = mCachedSize;
 
-    return *size < 0 ? *size : OK;
+    return *size < 0 ? *size : static_cast<status_t>(OK);
 }
 
 uint32_t MediaHTTP::flags() {
diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk
index e8d558c..93b7935 100644
--- a/media/libstagefright/httplive/Android.mk
+++ b/media/libstagefright/httplive/Android.mk
@@ -10,8 +10,7 @@
 
 LOCAL_C_INCLUDES:= \
 	$(TOP)/frameworks/av/media/libstagefright \
-	$(TOP)/frameworks/native/include/media/openmax \
-	$(TOP)/external/openssl/include
+	$(TOP)/frameworks/native/include/media/openmax
 
 LOCAL_CFLAGS += -Werror
 
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 874c118..f5328a6 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -49,6 +49,76 @@
 
 namespace android {
 
+// static
+// High water mark to start up switch or report prepared)
+const int64_t LiveSession::kHighWaterMark = 8000000ll;
+const int64_t LiveSession::kMidWaterMark = 5000000ll;
+const int64_t LiveSession::kLowWaterMark = 3000000ll;
+
+struct LiveSession::BandwidthEstimator : public RefBase {
+    BandwidthEstimator();
+
+    void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
+    bool estimateBandwidth(int32_t *bandwidth);
+
+private:
+    // Bandwidth estimation parameters
+    static const int32_t kMaxBandwidthHistoryItems = 20;
+    static const int64_t kMaxBandwidthHistoryWindowUs = 3000000ll; // 3 sec
+
+    struct BandwidthEntry {
+        int64_t mDelayUs;
+        size_t mNumBytes;
+    };
+
+    Mutex mLock;
+    List<BandwidthEntry> mBandwidthHistory;
+    int64_t mTotalTransferTimeUs;
+    size_t mTotalTransferBytes;
+
+    DISALLOW_EVIL_CONSTRUCTORS(BandwidthEstimator);
+};
+
+LiveSession::BandwidthEstimator::BandwidthEstimator() :
+    mTotalTransferTimeUs(0),
+    mTotalTransferBytes(0) {
+}
+
+void LiveSession::BandwidthEstimator::addBandwidthMeasurement(
+        size_t numBytes, int64_t delayUs) {
+    AutoMutex autoLock(mLock);
+
+    BandwidthEntry entry;
+    entry.mDelayUs = delayUs;
+    entry.mNumBytes = numBytes;
+    mTotalTransferTimeUs += delayUs;
+    mTotalTransferBytes += numBytes;
+    mBandwidthHistory.push_back(entry);
+
+    // trim old samples, keeping at least kMaxBandwidthHistoryItems samples,
+    // and total transfer time at least kMaxBandwidthHistoryWindowUs.
+    while (mBandwidthHistory.size() > kMaxBandwidthHistoryItems) {
+        List<BandwidthEntry>::iterator it = mBandwidthHistory.begin();
+        if (mTotalTransferTimeUs - it->mDelayUs < kMaxBandwidthHistoryWindowUs) {
+            break;
+        }
+        mTotalTransferTimeUs -= it->mDelayUs;
+        mTotalTransferBytes -= it->mNumBytes;
+        mBandwidthHistory.erase(mBandwidthHistory.begin());
+    }
+}
+
+bool LiveSession::BandwidthEstimator::estimateBandwidth(int32_t *bandwidthBps) {
+    AutoMutex autoLock(mLock);
+
+    if (mBandwidthHistory.size() < 2) {
+        return false;
+    }
+
+    *bandwidthBps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
+    return true;
+}
+
 LiveSession::LiveSession(
         const sp<AMessage> &notify, uint32_t flags,
         const sp<IMediaHTTPService> &httpService)
@@ -58,35 +128,35 @@
       mInPreparationPhase(true),
       mHTTPDataSource(new MediaHTTP(mHTTPService->makeHTTPConnection())),
       mCurBandwidthIndex(-1),
+      mBandwidthEstimator(new BandwidthEstimator()),
       mStreamMask(0),
       mNewStreamMask(0),
       mSwapMask(0),
-      mCheckBandwidthGeneration(0),
       mSwitchGeneration(0),
       mSubtitleGeneration(0),
       mLastDequeuedTimeUs(0ll),
       mRealTimeBaseUs(0ll),
       mReconfigurationInProgress(false),
       mSwitchInProgress(false),
-      mDisconnectReplyID(0),
-      mSeekReplyID(0),
       mFirstTimeUsValid(false),
       mFirstTimeUs(0),
-      mLastSeekTimeUs(0) {
+      mLastSeekTimeUs(0),
+      mPollBufferingGeneration(0) {
 
     mStreams[kAudioIndex] = StreamItem("audio");
     mStreams[kVideoIndex] = StreamItem("video");
     mStreams[kSubtitleIndex] = StreamItem("subtitles");
 
     for (size_t i = 0; i < kMaxStreams; ++i) {
-        mDiscontinuities.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
         mPacketSources.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
         mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
-        mBuffering[i] = false;
     }
 }
 
 LiveSession::~LiveSession() {
+    if (mFetcherLooper != NULL) {
+        mFetcherLooper->stop();
+    }
 }
 
 sp<ABuffer> LiveSession::createFormatChangeBuffer(bool swap) {
@@ -115,46 +185,42 @@
         return -EWOULDBLOCK;
     }
 
-    status_t finalResult;
-    sp<AnotherPacketSource> discontinuityQueue  = mDiscontinuities.valueFor(stream);
-    if (discontinuityQueue->hasBufferAvailable(&finalResult)) {
-        discontinuityQueue->dequeueAccessUnit(accessUnit);
-        // seeking, track switching
-        sp<AMessage> extra;
-        int64_t timeUs;
-        if ((*accessUnit)->meta()->findMessage("extra", &extra)
-                && extra != NULL
-                && extra->findInt64("timeUs", &timeUs)) {
-            // seeking only
-            mLastSeekTimeUs = timeUs;
-            mDiscontinuityOffsetTimesUs.clear();
-            mDiscontinuityAbsStartTimesUs.clear();
-        }
-        return INFO_DISCONTINUITY;
-    }
-
+    status_t finalResult = OK;
     sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
 
     ssize_t idx = typeToIndex(stream);
     if (!packetSource->hasBufferAvailable(&finalResult)) {
         if (finalResult == OK) {
-            mBuffering[idx] = true;
             return -EAGAIN;
         } else {
             return finalResult;
         }
     }
 
-    if (mBuffering[idx]) {
-        if (mSwitchInProgress
-                || packetSource->isFinished(0)
-                || packetSource->getEstimatedDurationUs() > 10000000ll) {
-            mBuffering[idx] = false;
-        }
+    // Do not let client pull data if we don't have format yet.
+    // We might only have a format discontinuity queued without actual data.
+    // When NuPlayerDecoder dequeues the format discontinuity, it will
+    // immediately try to getFormat. If we return NULL, NuPlayerDecoder
+    // thinks it can do seamless change, so will not shutdown decoder.
+    // When the actual format arrives, it can't handle it and get stuck.
+    // TODO: We need a method to check if the packet source has any
+    //       data packets available, dequeuing should only start then.
+    sp<MetaData> format = packetSource->getFormat();
+    if (format == NULL) {
+        return -EAGAIN;
+    }
+    int32_t targetDuration = 0;
+    sp<AMessage> meta = packetSource->getLatestEnqueuedMeta();
+    if (meta != NULL) {
+        meta->findInt32("targetDuration", &targetDuration);
     }
 
-    if (mBuffering[idx]) {
-        return -EAGAIN;
+    int64_t targetDurationUs = targetDuration * 1000000ll;
+    if (targetDurationUs == 0 ||
+            targetDurationUs > PlaylistFetcher::kMinBufferedDurationUs) {
+        // Fetchers limit buffering to
+        // min(3 * targetDuration, kMinBufferedDurationUs)
+        targetDurationUs = PlaylistFetcher::kMinBufferedDurationUs;
     }
 
     // wait for counterpart
@@ -220,7 +286,7 @@
                 Mutex::Autolock lock(mSwapMutex);
                 if (switchGeneration == mSwitchGeneration) {
                     swapPacketSource(stream);
-                    sp<AMessage> msg = new AMessage(kWhatSwapped, id());
+                    sp<AMessage> msg = new AMessage(kWhatSwapped, this);
                     msg->setInt32("stream", stream);
                     msg->setInt32("switchGeneration", switchGeneration);
                     msg->post();
@@ -325,7 +391,7 @@
 
 void LiveSession::connectAsync(
         const char *url, const KeyedVector<String8, String8> *headers) {
-    sp<AMessage> msg = new AMessage(kWhatConnect, id());
+    sp<AMessage> msg = new AMessage(kWhatConnect, this);
     msg->setString("url", url);
 
     if (headers != NULL) {
@@ -338,7 +404,7 @@
 }
 
 status_t LiveSession::disconnect() {
-    sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
+    sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
 
     sp<AMessage> response;
     status_t err = msg->postAndAwaitResponse(&response);
@@ -347,7 +413,7 @@
 }
 
 status_t LiveSession::seekTo(int64_t timeUs) {
-    sp<AMessage> msg = new AMessage(kWhatSeek, id());
+    sp<AMessage> msg = new AMessage(kWhatSeek, this);
     msg->setInt64("timeUs", timeUs);
 
     sp<AMessage> response;
@@ -378,7 +444,7 @@
 
         case kWhatSeek:
         {
-            uint32_t seekReplyID;
+            sp<AReplyToken> seekReplyID;
             CHECK(msg->senderAwaitsResponse(&seekReplyID));
             mSeekReplyID = seekReplyID;
             mSeekReply = new AMessage;
@@ -405,11 +471,16 @@
                     if (what == PlaylistFetcher::kWhatStopped) {
                         AString uri;
                         CHECK(msg->findString("uri", &uri));
-                        if (mFetcherInfos.removeItem(uri) < 0) {
+                        ssize_t index = mFetcherInfos.indexOfKey(uri);
+                        if (index < 0) {
                             // ignore duplicated kWhatStopped messages.
                             break;
                         }
 
+                        mFetcherLooper->unregisterHandler(
+                                mFetcherInfos[index].mFetcher->id());
+                        mFetcherInfos.removeItemsAt(index);
+
                         if (mSwitchInProgress) {
                             tryToFinishBandwidthSwitch();
                         }
@@ -419,14 +490,6 @@
                         CHECK_GT(mContinuationCounter, 0);
                         if (--mContinuationCounter == 0) {
                             mContinuation->post();
-
-                            if (mSeekReplyID != 0) {
-                                CHECK(mSeekReply != NULL);
-                                mSeekReply->setInt32("err", OK);
-                                mSeekReply->postReply(mSeekReplyID);
-                                mSeekReplyID = 0;
-                                mSeekReply.clear();
-                            }
                         }
                     }
                     break;
@@ -440,8 +503,11 @@
                     int64_t durationUs;
                     CHECK(msg->findInt64("durationUs", &durationUs));
 
-                    FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
-                    info->mDurationUs = durationUs;
+                    ssize_t index = mFetcherInfos.indexOfKey(uri);
+                    if (index >= 0) {
+                        FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
+                        info->mDurationUs = durationUs;
+                    }
                     break;
                 }
 
@@ -489,34 +555,6 @@
                     break;
                 }
 
-                case PlaylistFetcher::kWhatTemporarilyDoneFetching:
-                {
-                    AString uri;
-                    CHECK(msg->findString("uri", &uri));
-
-                    if (mFetcherInfos.indexOfKey(uri) < 0) {
-                        ALOGE("couldn't find uri");
-                        break;
-                    }
-                    FetcherInfo *info = &mFetcherInfos.editValueFor(uri);
-                    info->mIsPrepared = true;
-
-                    if (mInPreparationPhase) {
-                        bool allFetchersPrepared = true;
-                        for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
-                            if (!mFetcherInfos.valueAt(i).mIsPrepared) {
-                                allFetchersPrepared = false;
-                                break;
-                            }
-                        }
-
-                        if (allFetchersPrepared) {
-                            postPrepared(OK);
-                        }
-                    }
-                    break;
-                }
-
                 case PlaylistFetcher::kWhatStartedAt:
                 {
                     int32_t switchGeneration;
@@ -545,19 +583,6 @@
             break;
         }
 
-        case kWhatCheckBandwidth:
-        {
-            int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-
-            if (generation != mCheckBandwidthGeneration) {
-                break;
-            }
-
-            onCheckBandwidth(msg);
-            break;
-        }
-
         case kWhatChangeConfiguration:
         {
             onChangeConfiguration(msg);
@@ -588,15 +613,13 @@
             break;
         }
 
-        case kWhatCheckSwitchDown:
+        case kWhatPollBuffering:
         {
-            onCheckSwitchDown();
-            break;
-        }
-
-        case kWhatSwitchDown:
-        {
-            onSwitchDown();
+            int32_t generation;
+            CHECK(msg->findInt32("generation", &generation));
+            if (generation == mPollBufferingGeneration) {
+                onPollBuffering();
+            }
             break;
         }
 
@@ -667,6 +690,14 @@
         return;
     }
 
+    // create looper for fetchers
+    if (mFetcherLooper == NULL) {
+        mFetcherLooper = new ALooper();
+
+        mFetcherLooper->setName("Fetcher");
+        mFetcherLooper->start(false, false);
+    }
+
     // We trust the content provider to make a reasonable choice of preferred
     // initial bandwidth by listing it first in the variant playlist.
     // At startup we really don't have a good estimate on the available
@@ -685,7 +716,6 @@
             AString uri;
             mPlaylist->itemAt(i, &uri, &meta);
 
-            unsigned long bandwidth;
             CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
 
             if (initialBandwidth == 0) {
@@ -716,25 +746,26 @@
     mPlaylist->pickRandomMediaItems();
     changeConfiguration(
             0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
+
+    schedulePollBuffering();
 }
 
 void LiveSession::finishDisconnect() {
     // No reconfiguration is currently pending, make sure none will trigger
     // during disconnection either.
-    cancelCheckBandwidthEvent();
 
     // Protect mPacketSources from a swapPacketSource race condition through disconnect.
     // (finishDisconnect, onFinishDisconnect2)
     cancelBandwidthSwitch();
 
-    // cancel switch down monitor
-    mSwitchDownMonitor.clear();
+    // cancel buffer polling
+    cancelPollBuffering();
 
     for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
         mFetcherInfos.valueAt(i).mFetcher->stopAsync();
     }
 
-    sp<AMessage> msg = new AMessage(kWhatFinishDisconnect2, id());
+    sp<AMessage> msg = new AMessage(kWhatFinishDisconnect2, this);
 
     mContinuationCounter = mFetcherInfos.size();
     mContinuation = msg;
@@ -757,7 +788,7 @@
     response->setInt32("err", OK);
 
     response->postReply(mDisconnectReplyID);
-    mDisconnectReplyID = 0;
+    mDisconnectReplyID.clear();
 }
 
 sp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
@@ -767,7 +798,7 @@
         return NULL;
     }
 
-    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatFetcherNotify, this);
     notify->setString("uri", uri);
     notify->setInt32("switchGeneration", mSwitchGeneration);
 
@@ -776,7 +807,7 @@
     info.mDurationUs = -1ll;
     info.mIsPrepared = false;
     info.mToBeRemoved = false;
-    looper()->registerHandler(info.mFetcher);
+    mFetcherLooper->registerHandler(info.mFetcher);
 
     mFetcherInfos.add(uri, info);
 
@@ -823,11 +854,11 @@
                 headers.add(
                         String8("Range"),
                         String8(
-                            StringPrintf(
+                            AStringPrintf(
                                 "bytes=%lld-%s",
                                 range_offset,
                                 range_length < 0
-                                    ? "" : StringPrintf("%lld",
+                                    ? "" : AStringPrintf("%lld",
                                             range_offset + range_length - 1).c_str()).c_str()));
             }
             status_t err = mHTTPDataSource->connect(url, &headers);
@@ -859,7 +890,11 @@
         // Only resize when we don't know the size.
         size_t bufferRemaining = buffer->capacity() - buffer->size();
         if (bufferRemaining == 0 && getSizeErr != OK) {
-            bufferRemaining = 32768;
+            size_t bufferIncrement = buffer->size() / 2;
+            if (bufferIncrement < 32768) {
+                bufferIncrement = 32768;
+            }
+            bufferRemaining = bufferIncrement;
 
             ALOGV("increasing download buffer to %zu bytes",
                  buffer->size() + bufferRemaining);
@@ -962,12 +997,21 @@
     return playlist;
 }
 
+#if 0
 static double uniformRand() {
     return (double)rand() / RAND_MAX;
 }
+#endif
 
-size_t LiveSession::getBandwidthIndex() {
-    if (mBandwidthItems.size() == 0) {
+void LiveSession::addBandwidthMeasurement(size_t numBytes, int64_t delayUs) {
+    mBandwidthEstimator->addBandwidthMeasurement(numBytes, delayUs);
+}
+
+size_t LiveSession::getBandwidthIndex(int32_t bandwidthBps) {
+    if (mBandwidthItems.size() < 2) {
+        // shouldn't be here if we only have 1 bandwidth, check
+        // logic to get rid of redundant bandwidth polling
+        ALOGW("getBandwidthIndex() called for single bandwidth playlist!");
         return 0;
     }
 
@@ -985,15 +1029,6 @@
     }
 
     if (index < 0) {
-        int32_t bandwidthBps;
-        if (mHTTPDataSource != NULL
-                && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
-            ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
-        } else {
-            ALOGV("no bandwidth estimate.");
-            return 0;  // Pick the lowest bandwidth stream by default.
-        }
-
         char value[PROPERTY_VALUE_MAX];
         if (property_get("media.httplive.max-bw", value, NULL)) {
             char *end;
@@ -1010,15 +1045,9 @@
 
         index = mBandwidthItems.size() - 1;
         while (index > 0) {
-            // consider only 80% of the available bandwidth, but if we are switching up,
-            // be even more conservative (70%) to avoid overestimating and immediately
-            // switching back.
-            size_t adjustedBandwidthBps = bandwidthBps;
-            if (index > mCurBandwidthIndex) {
-                adjustedBandwidthBps = adjustedBandwidthBps * 7 / 10;
-            } else {
-                adjustedBandwidthBps = adjustedBandwidthBps * 8 / 10;
-            }
+            // be conservative (70%) to avoid overestimating and immediately
+            // switching down again.
+            size_t adjustedBandwidthBps = bandwidthBps * 7 / 10;
             if (mBandwidthItems.itemAt(index).mBandwidth <= adjustedBandwidthBps) {
                 break;
             }
@@ -1109,11 +1138,11 @@
 }
 
 status_t LiveSession::getDuration(int64_t *durationUs) const {
-    int64_t maxDurationUs = 0ll;
+    int64_t maxDurationUs = -1ll;
     for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
         int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
 
-        if (fetcherDurationUs >= 0ll && fetcherDurationUs > maxDurationUs) {
+        if (fetcherDurationUs > maxDurationUs) {
             maxDurationUs = fetcherDurationUs;
         }
     }
@@ -1156,7 +1185,7 @@
     ++mSubtitleGeneration;
     status_t err = mPlaylist->selectTrack(index, select);
     if (err == OK) {
-        sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, id());
+        sp<AMessage> msg = new AMessage(kWhatChangeConfiguration, this);
         msg->setInt32("bandwidthIndex", mCurBandwidthIndex);
         msg->setInt32("pickTrack", select);
         msg->post();
@@ -1164,17 +1193,12 @@
     return err;
 }
 
-bool LiveSession::canSwitchUp() {
-    // Allow upwards bandwidth switch when a stream has buffered at least 10 seconds.
-    status_t err = OK;
-    for (size_t i = 0; i < mPacketSources.size(); ++i) {
-        sp<AnotherPacketSource> source = mPacketSources.valueAt(i);
-        int64_t dur = source->getBufferedDurationUs(&err);
-        if (err == OK && dur > 10000000) {
-            return true;
-        }
+ssize_t LiveSession::getSelectedTrack(media_track_type type) const {
+    if (mPlaylist == NULL) {
+        return -1;
+    } else {
+        return mPlaylist->getSelectedTrack(type);
     }
-    return false;
 }
 
 void LiveSession::changeConfiguration(
@@ -1211,34 +1235,36 @@
 
         bool discardFetcher = true;
 
-        // If we're seeking all current fetchers are discarded.
         if (timeUs < 0ll) {
             // delay fetcher removal if not picking tracks
             discardFetcher = pickTrack;
 
-            for (size_t j = 0; j < kMaxStreams; ++j) {
-                StreamType type = indexToType(j);
-                if ((streamMask & type) && uri == URIs[j]) {
-                    resumeMask |= type;
-                    streamMask &= ~type;
-                    discardFetcher = false;
-                }
+        }
+
+        for (size_t j = 0; j < kMaxStreams; ++j) {
+            StreamType type = indexToType(j);
+            if ((streamMask & type) && uri == URIs[j]) {
+                resumeMask |= type;
+                streamMask &= ~type;
+                discardFetcher = false;
             }
         }
 
         if (discardFetcher) {
             mFetcherInfos.valueAt(i).mFetcher->stopAsync();
         } else {
-            mFetcherInfos.valueAt(i).mFetcher->pauseAsync();
+            // if we're seeking, pause immediately (no need to finish the segment)
+            bool immediate = (timeUs >= 0ll);
+            mFetcherInfos.valueAt(i).mFetcher->pauseAsync(immediate);
         }
     }
 
     sp<AMessage> msg;
     if (timeUs < 0ll) {
         // skip onChangeConfiguration2 (decoder destruction) if not seeking.
-        msg = new AMessage(kWhatChangeConfiguration3, id());
+        msg = new AMessage(kWhatChangeConfiguration3, this);
     } else {
-        msg = new AMessage(kWhatChangeConfiguration2, id());
+        msg = new AMessage(kWhatChangeConfiguration2, this);
     }
     msg->setInt32("streamMask", streamMask);
     msg->setInt32("resumeMask", resumeMask);
@@ -1259,14 +1285,6 @@
 
     if (mContinuationCounter == 0) {
         msg->post();
-
-        if (mSeekReplyID != 0) {
-            CHECK(mSeekReply != NULL);
-            mSeekReply->setInt32("err", OK);
-            mSeekReply->postReply(mSeekReplyID);
-            mSeekReplyID = 0;
-            mSeekReply.clear();
-        }
     }
 }
 
@@ -1286,13 +1304,34 @@
 
     // All fetchers are either suspended or have been removed now.
 
+    // If we're seeking, clear all packet sources before we report
+    // seek complete, to prevent decoder from pulling stale data.
+    int64_t timeUs;
+    CHECK(msg->findInt64("timeUs", &timeUs));
+
+    if (timeUs >= 0) {
+        mLastSeekTimeUs = timeUs;
+
+        for (size_t i = 0; i < mPacketSources.size(); i++) {
+            mPacketSources.editValueAt(i)->clear();
+        }
+
+        mDiscontinuityOffsetTimesUs.clear();
+        mDiscontinuityAbsStartTimesUs.clear();
+
+        if (mSeekReplyID != NULL) {
+            CHECK(mSeekReply != NULL);
+            mSeekReply->setInt32("err", OK);
+            mSeekReply->postReply(mSeekReplyID);
+            mSeekReplyID.clear();
+            mSeekReply.clear();
+        }
+    }
+
     uint32_t streamMask, resumeMask;
     CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
     CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
 
-    // currently onChangeConfiguration2 is only called for seeking;
-    // remove the following CHECK if using it else where.
-    CHECK_EQ(resumeMask, 0);
     streamMask |= resumeMask;
 
     AString URIs[kMaxStreams];
@@ -1304,17 +1343,25 @@
         }
     }
 
-    // Determine which decoders to shutdown on the player side,
-    // a decoder has to be shutdown if either
-    // 1) its streamtype was active before but now longer isn't.
-    // or
-    // 2) its streamtype was already active and still is but the URI
-    //    has changed.
     uint32_t changedMask = 0;
     for (size_t i = 0; i < kMaxStreams && i != kSubtitleIndex; ++i) {
-        if (((mStreamMask & streamMask & indexToType(i))
-                && !(URIs[i] == mStreams[i].mUri))
-                || (mStreamMask & ~streamMask & indexToType(i))) {
+        // stream URI could change even if onChangeConfiguration2 is only
+        // used for seek. Seek could happen during a bw switch, in this
+        // case bw switch will be cancelled, but the seekTo position will
+        // fetch from the new URI.
+        if ((mStreamMask & streamMask & indexToType(i))
+                && !mStreams[i].mUri.empty()
+                && !(URIs[i] == mStreams[i].mUri)) {
+            ALOGV("stream %zu changed: oldURI %s, newURI %s", i,
+                    mStreams[i].mUri.c_str(), URIs[i].c_str());
+            sp<AnotherPacketSource> source = mPacketSources.valueFor(indexToType(i));
+            source->queueDiscontinuity(
+                    ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
+        }
+        // Determine which decoders to shutdown on the player side,
+        // a decoder has to be shutdown if its streamtype was active
+        // before but now longer isn't.
+        if ((mStreamMask & ~streamMask & indexToType(i))) {
             changedMask |= indexToType(i);
         }
     }
@@ -1335,7 +1382,7 @@
     notify->setInt32("changedMask", changedMask);
 
     msg->setWhat(kWhatChangeConfiguration3);
-    msg->setTarget(id());
+    msg->setTarget(this);
 
     notify->setMessage("reply", msg);
     notify->post();
@@ -1391,24 +1438,13 @@
         for (size_t j = 0; j < kMaxStreams; ++j) {
             if ((resumeMask & indexToType(j)) && uri == mStreams[j].mUri) {
                 sources[j] = mPacketSources.valueFor(indexToType(j));
-
-                if (j != kSubtitleIndex) {
-                    ALOGV("queueing dummy discontinuity for stream type %d", indexToType(j));
-                    sp<AnotherPacketSource> discontinuityQueue;
-                    discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
-                    discontinuityQueue->queueDiscontinuity(
-                            ATSParser::DISCONTINUITY_NONE,
-                            NULL,
-                            true);
-                }
             }
         }
-
         FetcherInfo &info = mFetcherInfos.editValueAt(i);
         if (sources[kAudioIndex] != NULL || sources[kVideoIndex] != NULL
                 || sources[kSubtitleIndex] != NULL) {
             info.mFetcher->startAsync(
-                    sources[kAudioIndex], sources[kVideoIndex], sources[kSubtitleIndex]);
+                    sources[kAudioIndex], sources[kVideoIndex], sources[kSubtitleIndex], timeUs);
         } else {
             info.mToBeRemoved = true;
         }
@@ -1433,7 +1469,6 @@
         sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
         CHECK(fetcher != NULL);
 
-        int32_t latestSeq = -1;
         int64_t startTimeUs = -1;
         int64_t segmentStartTimeUs = -1ll;
         int32_t discontinuitySeq = -1;
@@ -1450,18 +1485,9 @@
                 sources[j] = mPacketSources.valueFor(indexToType(j));
 
                 if (timeUs >= 0) {
-                    sources[j]->clear();
                     startTimeUs = timeUs;
-
-                    sp<AnotherPacketSource> discontinuityQueue;
-                    sp<AMessage> extra = new AMessage;
-                    extra->setInt64("timeUs", timeUs);
-                    discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
-                    discontinuityQueue->queueDiscontinuity(
-                            ATSParser::DISCONTINUITY_TIME, extra, true);
                 } else {
                     int32_t type;
-                    int64_t srcSegmentStartTimeUs;
                     sp<AMessage> meta;
                     if (pickTrack) {
                         // selecting
@@ -1473,14 +1499,15 @@
 
                     if (meta != NULL && !meta->findInt32("discontinuity", &type)) {
                         int64_t tmpUs;
-                        CHECK(meta->findInt64("timeUs", &tmpUs));
-                        if (startTimeUs < 0 || tmpUs < startTimeUs) {
-                            startTimeUs = tmpUs;
-                        }
+                        int64_t tmpSegmentUs;
 
-                        CHECK(meta->findInt64("segmentStartTimeUs", &tmpUs));
-                        if (segmentStartTimeUs < 0 || tmpUs < segmentStartTimeUs) {
-                            segmentStartTimeUs = tmpUs;
+                        CHECK(meta->findInt64("timeUs", &tmpUs));
+                        CHECK(meta->findInt64("segmentStartTimeUs", &tmpSegmentUs));
+                        if (startTimeUs < 0 || tmpSegmentUs < segmentStartTimeUs) {
+                            startTimeUs = tmpUs;
+                            segmentStartTimeUs = tmpSegmentUs;
+                        } else if (tmpSegmentUs == segmentStartTimeUs && tmpUs < startTimeUs) {
+                            startTimeUs = tmpUs;
                         }
 
                         int32_t seq;
@@ -1496,9 +1523,10 @@
                         if (j == kSubtitleIndex) {
                             break;
                         }
-                        sp<AnotherPacketSource> discontinuityQueue;
-                        discontinuityQueue = mDiscontinuities.valueFor(indexToType(j));
-                        discontinuityQueue->queueDiscontinuity(
+
+                        ALOGV("stream[%zu]: queue format change", j);
+
+                        sources[j]->queueDiscontinuity(
                                 ATSParser::DISCONTINUITY_FORMATCHANGE, NULL, true);
                     } else {
                         // adapting, queue discontinuities after resume
@@ -1528,9 +1556,6 @@
     // All fetchers have now been started, the configuration change
     // has completed.
 
-    cancelCheckBandwidthEvent();
-    scheduleCheckBandwidthEvent();
-
     ALOGV("XXX configuration change completed.");
     mReconfigurationInProgress = false;
     if (switching) {
@@ -1539,7 +1564,7 @@
         mStreamMask = mNewStreamMask;
     }
 
-    if (mDisconnectReplyID != 0) {
+    if (mDisconnectReplyID != NULL) {
         finishDisconnect();
     }
 }
@@ -1587,42 +1612,35 @@
     tryToFinishBandwidthSwitch();
 }
 
-void LiveSession::onCheckSwitchDown() {
-    if (mSwitchDownMonitor == NULL) {
-        return;
-    }
+void LiveSession::schedulePollBuffering() {
+    sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
+    msg->setInt32("generation", mPollBufferingGeneration);
+    msg->post(1000000ll);
+}
 
-    for (size_t i = 0; i < kMaxStreams; ++i) {
-        int32_t targetDuration;
-        sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(indexToType(i));
-        sp<AMessage> meta = packetSource->getLatestDequeuedMeta();
+void LiveSession::cancelPollBuffering() {
+    ++mPollBufferingGeneration;
+}
 
-        if (meta != NULL && meta->findInt32("targetDuration", &targetDuration) ) {
-            int64_t bufferedDurationUs = packetSource->getEstimatedDurationUs();
-            int64_t targetDurationUs = targetDuration * 1000000ll;
+void LiveSession::onPollBuffering() {
+    ALOGV("onPollBuffering: mSwitchInProgress %d, mReconfigurationInProgress %d, "
+            "mInPreparationPhase %d, mCurBandwidthIndex %d, mStreamMask 0x%x",
+        mSwitchInProgress, mReconfigurationInProgress,
+        mInPreparationPhase, mCurBandwidthIndex, mStreamMask);
 
-            if (bufferedDurationUs < targetDurationUs / 3) {
-                (new AMessage(kWhatSwitchDown, id()))->post();
-                break;
-            }
+    bool low, mid, high;
+    if (checkBuffering(low, mid, high)) {
+        if (mInPreparationPhase && mid) {
+            postPrepared(OK);
+        }
+
+        // don't switch before we report prepared
+        if (!mInPreparationPhase) {
+            switchBandwidthIfNeeded(high, !mid);
         }
     }
 
-    mSwitchDownMonitor->post(1000000ll);
-}
-
-void LiveSession::onSwitchDown() {
-    if (mReconfigurationInProgress || mSwitchInProgress || mCurBandwidthIndex == 0) {
-        return;
-    }
-
-    ssize_t bandwidthIndex = getBandwidthIndex();
-    if (bandwidthIndex < mCurBandwidthIndex) {
-        changeConfiguration(-1, bandwidthIndex, false);
-        return;
-    }
-
-    changeConfiguration(-1, mCurBandwidthIndex - 1, false);
+    schedulePollBuffering();
 }
 
 // Mark switch done when:
@@ -1647,16 +1665,6 @@
     }
 }
 
-void LiveSession::scheduleCheckBandwidthEvent() {
-    sp<AMessage> msg = new AMessage(kWhatCheckBandwidth, id());
-    msg->setInt32("generation", mCheckBandwidthGeneration);
-    msg->post(10000000ll);
-}
-
-void LiveSession::cancelCheckBandwidthEvent() {
-    ++mCheckBandwidthGeneration;
-}
-
 void LiveSession::cancelBandwidthSwitch() {
     Mutex::Autolock lock(mSwapMutex);
     mSwitchGeneration++;
@@ -1686,33 +1694,93 @@
     }
 }
 
-bool LiveSession::canSwitchBandwidthTo(size_t bandwidthIndex) {
-    if (mReconfigurationInProgress || mSwitchInProgress) {
+bool LiveSession::checkBuffering(bool &low, bool &mid, bool &high) {
+    low = mid = high = false;
+
+    if (mSwitchInProgress || mReconfigurationInProgress) {
+        ALOGV("Switch/Reconfig in progress, defer buffer polling");
         return false;
     }
 
-    if (mCurBandwidthIndex < 0) {
+    // TODO: Fine tune low/high mark.
+    //       We also need to pause playback if buffering is too low.
+    //       Currently during underflow, we depend on decoder to starve
+    //       to pause, but A/V could have different buffering left,
+    //       they're not paused together.
+    // TODO: Report buffering level to NuPlayer for BUFFERING_UPDATE
+
+    // Switch down if any of the fetchers are below low mark;
+    // Switch up   if all of the fetchers are over high mark.
+    size_t activeCount, lowCount, midCount, highCount;
+    activeCount = lowCount = midCount = highCount = 0;
+    for (size_t i = 0; i < mPacketSources.size(); ++i) {
+        // we don't check subtitles for buffering level
+        if (!(mStreamMask & mPacketSources.keyAt(i)
+                & (STREAMTYPE_AUDIO | STREAMTYPE_VIDEO))) {
+            continue;
+        }
+        // ignore streams that never had any packet queued.
+        // (it's possible that the variant only has audio or video)
+        sp<AMessage> meta = mPacketSources[i]->getLatestEnqueuedMeta();
+        if (meta == NULL) {
+            continue;
+        }
+
+        ++activeCount;
+        int64_t bufferedDurationUs =
+                mPacketSources[i]->getEstimatedDurationUs();
+        ALOGV("source[%zu]: buffered %lld us", i, (long long)bufferedDurationUs);
+        if (bufferedDurationUs < kLowWaterMark) {
+            ++lowCount;
+            break;
+        } else if (bufferedDurationUs > kHighWaterMark) {
+            ++midCount;
+            ++highCount;
+        } else if (bufferedDurationUs > kMidWaterMark) {
+            ++midCount;
+        }
+    }
+
+    if (activeCount > 0) {
+        high = (highCount == activeCount);
+        mid = (midCount == activeCount);
+        low = (lowCount > 0);
         return true;
     }
 
-    if (bandwidthIndex == (size_t)mCurBandwidthIndex) {
-        return false;
-    } else if (bandwidthIndex > (size_t)mCurBandwidthIndex) {
-        return canSwitchUp();
-    } else {
-        return true;
-    }
+    return false;
 }
 
-void LiveSession::onCheckBandwidth(const sp<AMessage> &msg) {
-    size_t bandwidthIndex = getBandwidthIndex();
-    if (canSwitchBandwidthTo(bandwidthIndex)) {
-        changeConfiguration(-1ll /* timeUs */, bandwidthIndex);
+void LiveSession::switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow) {
+    // no need to check bandwidth if we only have 1 bandwidth settings
+    if (mBandwidthItems.size() < 2) {
+        return;
+    }
+
+    int32_t bandwidthBps;
+    if (mBandwidthEstimator->estimateBandwidth(&bandwidthBps)) {
+        ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
     } else {
-        // Come back and check again 10 seconds later in case there is nothing to do now.
-        // If we DO change configuration, once that completes it'll schedule a new
-        // check bandwidth event with an incremented mCheckBandwidthGeneration.
-        msg->post(10000000ll);
+        ALOGV("no bandwidth estimate.");
+        return;
+    }
+
+    int32_t curBandwidth = mBandwidthItems.itemAt(mCurBandwidthIndex).mBandwidth;
+    bool bandwidthLow = bandwidthBps < (int32_t)curBandwidth * 8 / 10;
+    bool bandwidthHigh = bandwidthBps > (int32_t)curBandwidth * 12 / 10;
+
+    if ((bufferHigh && bandwidthHigh) || (bufferLow && bandwidthLow)) {
+        ssize_t bandwidthIndex = getBandwidthIndex(bandwidthBps);
+
+        if (bandwidthIndex == mCurBandwidthIndex
+                || (bufferHigh && bandwidthIndex < mCurBandwidthIndex)
+                || (bufferLow && bandwidthIndex > mCurBandwidthIndex)) {
+            return;
+        }
+
+        ALOGI("#### Initiate Bandwidth Switch: %d => %d",
+                mCurBandwidthIndex, bandwidthIndex);
+        changeConfiguration(-1, bandwidthIndex, false);
     }
 }
 
@@ -1730,10 +1798,8 @@
     notify->post();
 
     mInPreparationPhase = false;
-
-    mSwitchDownMonitor = new AMessage(kWhatCheckSwitchDown, id());
-    mSwitchDownMonitor->post();
 }
 
+
 }  // namespace android
 
diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h
index 7aacca6..685fefa 100644
--- a/media/libstagefright/httplive/LiveSession.h
+++ b/media/libstagefright/httplive/LiveSession.h
@@ -19,12 +19,14 @@
 #define LIVE_SESSION_H_
 
 #include <media/stagefright/foundation/AHandler.h>
+#include <media/mediaplayer.h>
 
 #include <utils/String8.h>
 
 namespace android {
 
 struct ABuffer;
+struct AReplyToken;
 struct AnotherPacketSource;
 struct DataSource;
 struct HTTPBase;
@@ -32,17 +34,12 @@
 struct LiveDataSource;
 struct M3UParser;
 struct PlaylistFetcher;
-struct Parcel;
 
 struct LiveSession : public AHandler {
     enum Flags {
         // Don't log any URLs.
         kFlagIncognito = 1,
     };
-    LiveSession(
-            const sp<AMessage> &notify,
-            uint32_t flags,
-            const sp<IMediaHTTPService> &httpService);
 
     enum StreamIndex {
         kAudioIndex    = 0,
@@ -56,6 +53,12 @@
         STREAMTYPE_VIDEO        = 1 << kVideoIndex,
         STREAMTYPE_SUBTITLES    = 1 << kSubtitleIndex,
     };
+
+    LiveSession(
+            const sp<AMessage> &notify,
+            uint32_t flags,
+            const sp<IMediaHTTPService> &httpService);
+
     status_t dequeueAccessUnit(StreamType stream, sp<ABuffer> *accessUnit);
 
     status_t getStreamFormat(StreamType stream, sp<AMessage> *format);
@@ -73,6 +76,7 @@
     size_t getTrackCount() const;
     sp<AMessage> getTrackInfo(size_t trackIndex) const;
     status_t selectTrack(size_t index, bool select);
+    ssize_t getSelectedTrack(media_track_type /* type */) const;
 
     bool isSeekable() const;
     bool hasDynamicDuration() const;
@@ -102,16 +106,19 @@
         kWhatDisconnect                 = 'disc',
         kWhatSeek                       = 'seek',
         kWhatFetcherNotify              = 'notf',
-        kWhatCheckBandwidth             = 'bndw',
         kWhatChangeConfiguration        = 'chC0',
         kWhatChangeConfiguration2       = 'chC2',
         kWhatChangeConfiguration3       = 'chC3',
         kWhatFinishDisconnect2          = 'fin2',
         kWhatSwapped                    = 'swap',
-        kWhatCheckSwitchDown            = 'ckSD',
-        kWhatSwitchDown                 = 'sDwn',
+        kWhatPollBuffering              = 'poll',
     };
 
+    static const int64_t kHighWaterMark;
+    static const int64_t kMidWaterMark;
+    static const int64_t kLowWaterMark;
+
+    struct BandwidthEstimator;
     struct BandwidthItem {
         size_t mPlaylistIndex;
         unsigned long mBandwidth;
@@ -162,9 +169,11 @@
 
     Vector<BandwidthItem> mBandwidthItems;
     ssize_t mCurBandwidthIndex;
+    sp<BandwidthEstimator> mBandwidthEstimator;
 
     sp<M3UParser> mPlaylist;
 
+    sp<ALooper> mFetcherLooper;
     KeyedVector<AString, FetcherInfo> mFetcherInfos;
     uint32_t mStreamMask;
 
@@ -177,7 +186,6 @@
     // we use this to track reconfiguration progress.
     uint32_t mSwapMask;
 
-    KeyedVector<StreamType, sp<AnotherPacketSource> > mDiscontinuities;
     KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources;
     // A second set of packet sources that buffer content for the variant we're switching to.
     KeyedVector<StreamType, sp<AnotherPacketSource> > mPacketSources2;
@@ -187,7 +195,6 @@
     // * a forced bandwidth switch termination in cancelSwitch on the live looper.
     Mutex mSwapMutex;
 
-    int32_t mCheckBandwidthGeneration;
     int32_t mSwitchGeneration;
     int32_t mSubtitleGeneration;
 
@@ -200,16 +207,17 @@
 
     bool mReconfigurationInProgress;
     bool mSwitchInProgress;
-    uint32_t mDisconnectReplyID;
-    uint32_t mSeekReplyID;
+    sp<AReplyToken> mDisconnectReplyID;
+    sp<AReplyToken> mSeekReplyID;
 
     bool mFirstTimeUsValid;
     int64_t mFirstTimeUs;
     int64_t mLastSeekTimeUs;
-    sp<AMessage> mSwitchDownMonitor;
     KeyedVector<size_t, int64_t> mDiscontinuityAbsStartTimesUs;
     KeyedVector<size_t, int64_t> mDiscontinuityOffsetTimesUs;
 
+    int32_t mPollBufferingGeneration;
+
     sp<PlaylistFetcher> addFetcher(const char *uri);
 
     void onConnect(const sp<AMessage> &msg);
@@ -240,7 +248,8 @@
     sp<M3UParser> fetchPlaylist(
             const char *url, uint8_t *curPlaylistHash, bool *unchanged);
 
-    size_t getBandwidthIndex();
+    void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
+    size_t getBandwidthIndex(int32_t bandwidthBps);
     int64_t latestMediaSegmentStartTimeUs();
 
     static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *);
@@ -253,27 +262,24 @@
     void onChangeConfiguration2(const sp<AMessage> &msg);
     void onChangeConfiguration3(const sp<AMessage> &msg);
     void onSwapped(const sp<AMessage> &msg);
-    void onCheckSwitchDown();
-    void onSwitchDown();
     void tryToFinishBandwidthSwitch();
 
-    void scheduleCheckBandwidthEvent();
-    void cancelCheckBandwidthEvent();
-
     // cancelBandwidthSwitch is atomic wrt swapPacketSource; call it to prevent packet sources
     // from being swapped out on stale discontinuities while manipulating
     // mPacketSources/mPacketSources2.
     void cancelBandwidthSwitch();
 
-    bool canSwitchBandwidthTo(size_t bandwidthIndex);
-    void onCheckBandwidth(const sp<AMessage> &msg);
+    void schedulePollBuffering();
+    void cancelPollBuffering();
+    void onPollBuffering();
+    bool checkBuffering(bool &low, bool &mid, bool &high);
+    void switchBandwidthIfNeeded(bool bufferHigh, bool bufferLow);
 
     void finishDisconnect();
 
     void postPrepared(status_t err);
 
     void swapPacketSource(StreamType stream);
-    bool canSwitchUp();
 
     DISALLOW_EVIL_CONSTRUCTORS(LiveSession);
 };
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index 1651dee..3c5d7cf 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -35,6 +35,7 @@
         TYPE_AUDIO,
         TYPE_VIDEO,
         TYPE_SUBS,
+        TYPE_CC,
     };
 
     enum FlagBits {
@@ -66,6 +67,9 @@
     virtual ~MediaGroup();
 
 private:
+
+    friend struct M3UParser;
+
     struct Media {
         AString mName;
         AString mURI;
@@ -247,6 +251,7 @@
       mIsComplete(false),
       mIsEvent(false),
       mDiscontinuitySeq(0),
+      mDiscontinuityCount(0),
       mSelectedIndex(-1) {
     mInitCheck = parse(data, size);
 }
@@ -356,6 +361,38 @@
     return mSelectedIndex;
 }
 
+ssize_t M3UParser::getSelectedTrack(media_track_type type) const {
+    MediaGroup::Type groupType;
+    switch (type) {
+        case MEDIA_TRACK_TYPE_VIDEO:
+            groupType = MediaGroup::TYPE_VIDEO;
+            break;
+
+        case MEDIA_TRACK_TYPE_AUDIO:
+            groupType = MediaGroup::TYPE_AUDIO;
+            break;
+
+        case MEDIA_TRACK_TYPE_SUBTITLE:
+            groupType = MediaGroup::TYPE_SUBS;
+            break;
+
+        default:
+            return -1;
+    }
+
+    for (size_t i = 0, ii = 0; i < mMediaGroups.size(); ++i) {
+        sp<MediaGroup> group = mMediaGroups.valueAt(i);
+        size_t tracks = group->countTracks();
+        if (groupType != group->mType) {
+            ii += tracks;
+        } else if (group->mSelectedIndex >= 0) {
+            return ii + group->mSelectedIndex;
+        }
+    }
+
+    return -1;
+}
+
 bool M3UParser::getTypeURI(size_t index, const char *key, AString *uri) const {
     if (!mIsVariantPlaylist) {
         *uri = mBaseURI;
@@ -546,6 +583,7 @@
                     itemMeta = new AMessage;
                 }
                 itemMeta->setInt32("discontinuity", true);
+                ++mDiscontinuityCount;
             } else if (line.startsWith("#EXT-X-STREAM-INF")) {
                 if (mMeta != NULL) {
                     return ERROR_MALFORMED;
@@ -573,6 +611,9 @@
             } else if (line.startsWith("#EXT-X-MEDIA")) {
                 err = parseMedia(line);
             } else if (line.startsWith("#EXT-X-DISCONTINUITY-SEQUENCE")) {
+                if (mIsVariantPlaylist) {
+                    return ERROR_MALFORMED;
+                }
                 size_t seq;
                 err = parseDiscontinuitySequence(line, &seq);
                 if (err == OK) {
@@ -592,6 +633,7 @@
                         || !itemMeta->findInt64("durationUs", &durationUs)) {
                     return ERROR_MALFORMED;
                 }
+                itemMeta->setInt32("discontinuity-sequence", mDiscontinuitySeq + mDiscontinuityCount);
             }
 
             mItems.push();
@@ -956,6 +998,8 @@
                 groupType = MediaGroup::TYPE_AUDIO;
             } else if (!strcasecmp("video", val.c_str())) {
                 groupType = MediaGroup::TYPE_VIDEO;
+            } else if (!strcasecmp("closed-captions", val.c_str())){
+                groupType = MediaGroup::TYPE_CC;
             } else {
                 ALOGE("Invalid media group type '%s'", val.c_str());
                 return ERROR_MALFORMED;
@@ -1068,6 +1112,13 @@
         return ERROR_MALFORMED;
     }
 
+    if (groupType == MediaGroup::TYPE_CC) {
+        // TODO: ignore this for now.
+        // CC track will be detected by CCDecoder. But we still need to
+        // pass the CC track flags (lang, auto) to the app in the future.
+        return OK;
+    }
+
     uint32_t flags = 0;
     if (haveGroupAutoselect && groupAutoselect) {
         flags |= MediaGroup::FLAG_AUTOSELECT;
diff --git a/media/libstagefright/httplive/M3UParser.h b/media/libstagefright/httplive/M3UParser.h
index d588afe..d475683 100644
--- a/media/libstagefright/httplive/M3UParser.h
+++ b/media/libstagefright/httplive/M3UParser.h
@@ -21,6 +21,7 @@
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AString.h>
+#include <media/mediaplayer.h>
 #include <utils/Vector.h>
 
 namespace android {
@@ -46,6 +47,7 @@
     size_t getTrackCount() const;
     sp<AMessage> getTrackInfo(size_t index) const;
     ssize_t getSelectedIndex() const;
+    ssize_t getSelectedTrack(media_track_type /* type */) const;
 
     bool getTypeURI(size_t index, const char *key, AString *uri) const;
 
@@ -68,6 +70,7 @@
     bool mIsComplete;
     bool mIsEvent;
     size_t mDiscontinuitySeq;
+    int32_t mDiscontinuityCount;
 
     sp<AMessage> mMeta;
     Vector<Item> mItems;
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 89181b5..a447010 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -49,8 +49,10 @@
 // static
 const int64_t PlaylistFetcher::kMinBufferedDurationUs = 10000000ll;
 const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll;
-const int32_t PlaylistFetcher::kDownloadBlockSize = 2048;
-const int32_t PlaylistFetcher::kNumSkipFrames = 10;
+const int64_t PlaylistFetcher::kFetcherResumeThreshold = 100000ll;
+// LCM of 188 (size of a TS packet) & 1k works well
+const int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024;
+const int32_t PlaylistFetcher::kNumSkipFrames = 5;
 
 PlaylistFetcher::PlaylistFetcher(
         const sp<AMessage> &notify,
@@ -58,7 +60,6 @@
         const char *uri,
         int32_t subtitleGeneration)
     : mNotify(notify),
-      mStartTimeUsNotify(notify->dup()),
       mSession(session),
       mURI(uri),
       mStreamTypeMask(0),
@@ -72,16 +73,16 @@
       mStartup(true),
       mAdaptive(false),
       mPrepared(false),
+      mTimeChangeSignaled(false),
       mNextPTSTimeUs(-1ll),
       mMonitorQueueGeneration(0),
       mSubtitleGeneration(subtitleGeneration),
+      mLastDiscontinuitySeq(-1ll),
+      mStopping(false),
       mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY),
       mFirstPTSValid(false),
-      mAbsoluteTimeAnchorUs(0ll),
       mVideoBuffer(new AnotherPacketSource(NULL)) {
     memset(mPlaylistHash, 0, sizeof(mPlaylistHash));
-    mStartTimeUsNotify->setInt32("what", kWhatStartedAt);
-    mStartTimeUsNotify->setInt32("streamMask", 0);
 }
 
 PlaylistFetcher::~PlaylistFetcher() {
@@ -290,7 +291,6 @@
 }
 
 status_t PlaylistFetcher::checkDecryptPadding(const sp<ABuffer> &buffer) {
-    status_t err;
     AString method;
     CHECK(buffer->meta()->findString("cipher-method", &method));
     if (method == "NONE") {
@@ -325,7 +325,7 @@
         ALOGV("Need to refresh playlist in %" PRId64 , maxDelayUs);
         delayUs = maxDelayUs;
     }
-    sp<AMessage> msg = new AMessage(kWhatMonitorQueue, id());
+    sp<AMessage> msg = new AMessage(kWhatMonitorQueue, this);
     msg->setInt32("generation", mMonitorQueueGeneration);
     msg->post(delayUs);
 }
@@ -334,6 +334,11 @@
     ++mMonitorQueueGeneration;
 }
 
+void PlaylistFetcher::setStopping(bool stopping) {
+    AutoMutex _l(mStoppingLock);
+    mStopping = stopping;
+}
+
 void PlaylistFetcher::startAsync(
         const sp<AnotherPacketSource> &audioSource,
         const sp<AnotherPacketSource> &videoSource,
@@ -342,7 +347,7 @@
         int64_t segmentStartTimeUs,
         int32_t startDiscontinuitySeq,
         bool adaptive) {
-    sp<AMessage> msg = new AMessage(kWhatStart, id());
+    sp<AMessage> msg = new AMessage(kWhatStart, this);
 
     uint32_t streamTypeMask = 0ul;
 
@@ -369,18 +374,23 @@
     msg->post();
 }
 
-void PlaylistFetcher::pauseAsync() {
-    (new AMessage(kWhatPause, id()))->post();
+void PlaylistFetcher::pauseAsync(bool immediate) {
+    if (immediate) {
+        setStopping(true);
+    }
+    (new AMessage(kWhatPause, this))->post();
 }
 
 void PlaylistFetcher::stopAsync(bool clear) {
-    sp<AMessage> msg = new AMessage(kWhatStop, id());
+    setStopping(true);
+
+    sp<AMessage> msg = new AMessage(kWhatStop, this);
     msg->setInt32("clear", clear);
     msg->post();
 }
 
 void PlaylistFetcher::resumeUntilAsync(const sp<AMessage> &params) {
-    AMessage* msg = new AMessage(kWhatResumeUntil, id());
+    AMessage* msg = new AMessage(kWhatResumeUntil, this);
     msg->setMessage("params", params);
     msg->post();
 }
@@ -450,6 +460,10 @@
 
 status_t PlaylistFetcher::onStart(const sp<AMessage> &msg) {
     mPacketSources.clear();
+    mStopParams.clear();
+    mStartTimeUsNotify = mNotify->dup();
+    mStartTimeUsNotify->setInt32("what", kWhatStartedAt);
+    mStartTimeUsNotify->setInt32("streamMask", 0);
 
     uint32_t streamTypeMask;
     CHECK(msg->findInt32("streamTypeMask", (int32_t *)&streamTypeMask));
@@ -495,12 +509,18 @@
     mSegmentStartTimeUs = segmentStartTimeUs;
     mDiscontinuitySeq = startDiscontinuitySeq;
 
+    mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
+
     if (startTimeUs >= 0) {
         mStartTimeUs = startTimeUs;
+        mFirstPTSValid = false;
         mSeqNumber = -1;
         mStartup = true;
         mPrepared = false;
+        mIDRFound = false;
+        mTimeChangeSignaled = false;
         mAdaptive = adaptive;
+        mVideoBuffer->clear();
     }
 
     postMonitorQueue();
@@ -510,6 +530,9 @@
 
 void PlaylistFetcher::onPause() {
     cancelMonitorQueue();
+    mLastDiscontinuitySeq = mDiscontinuitySeq;
+
+    setStopping(false);
 }
 
 void PlaylistFetcher::onStop(const sp<AMessage> &msg) {
@@ -526,6 +549,8 @@
 
     mPacketSources.clear();
     mStreamTypeMask = 0;
+
+    setStopping(false);
 }
 
 // Resume until we have reached the boundary timestamps listed in `msg`; when
@@ -535,12 +560,19 @@
     sp<AMessage> params;
     CHECK(msg->findMessage("params", &params));
 
-    bool stop = false;
+    size_t stopCount = 0;
     for (size_t i = 0; i < mPacketSources.size(); i++) {
         sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
 
         const char *stopKey;
         int streamType = mPacketSources.keyAt(i);
+
+        if (streamType == LiveSession::STREAMTYPE_SUBTITLES) {
+            // the subtitle track can always be stopped
+            ++stopCount;
+            continue;
+        }
+
         switch (streamType) {
         case LiveSession::STREAMTYPE_VIDEO:
             stopKey = "timeUsVideo";
@@ -550,29 +582,26 @@
             stopKey = "timeUsAudio";
             break;
 
-        case LiveSession::STREAMTYPE_SUBTITLES:
-            stopKey = "timeUsSubtitle";
-            break;
-
         default:
             TRESPASS();
         }
 
-        // Don't resume if we would stop within a resume threshold.
+        // check if this stream has too little data left to be resumed
         int32_t discontinuitySeq;
         int64_t latestTimeUs = 0, stopTimeUs = 0;
-        sp<AMessage> latestMeta = packetSource->getLatestDequeuedMeta();
+        sp<AMessage> latestMeta = packetSource->getLatestEnqueuedMeta();
         if (latestMeta != NULL
                 && latestMeta->findInt32("discontinuitySeq", &discontinuitySeq)
                 && discontinuitySeq == mDiscontinuitySeq
                 && latestMeta->findInt64("timeUs", &latestTimeUs)
                 && params->findInt64(stopKey, &stopTimeUs)
-                && stopTimeUs - latestTimeUs < resumeThreshold(latestMeta)) {
-            stop = true;
+                && stopTimeUs - latestTimeUs < kFetcherResumeThreshold) {
+            ++stopCount;
         }
     }
 
-    if (stop) {
+    // Don't resume if all streams are within a resume threshold
+    if (stopCount == mPacketSources.size()) {
         for (size_t i = 0; i < mPacketSources.size(); i++) {
             mPacketSources.valueAt(i)->queueAccessUnit(mSession->createFormatChangeBuffer());
         }
@@ -581,7 +610,7 @@
     }
 
     mStopParams = params;
-    postMonitorQueue();
+    onDownloadNext();
 
     return OK;
 }
@@ -610,31 +639,32 @@
     int32_t targetDurationSecs;
     int64_t targetDurationUs = kMinBufferedDurationUs;
     if (mPlaylist != NULL) {
-        CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
+        if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
+                "target-duration", &targetDurationSecs)) {
+            ALOGE("Playlist is missing required EXT-X-TARGETDURATION tag");
+            notifyError(ERROR_MALFORMED);
+            return;
+        }
         targetDurationUs = targetDurationSecs * 1000000ll;
     }
 
-    // buffer at least 3 times the target duration, or up to 10 seconds
-    int64_t durationToBufferUs = targetDurationUs * 3;
-    if (durationToBufferUs > kMinBufferedDurationUs)  {
-        durationToBufferUs = kMinBufferedDurationUs;
-    }
-
     int64_t bufferedDurationUs = 0ll;
-    status_t finalResult = NOT_ENOUGH_DATA;
+    status_t finalResult = OK;
     if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
         sp<AnotherPacketSource> packetSource =
             mPacketSources.valueFor(LiveSession::STREAMTYPE_SUBTITLES);
 
         bufferedDurationUs =
                 packetSource->getBufferedDurationUs(&finalResult);
-        finalResult = OK;
     } else {
-        // Use max stream duration to prevent us from waiting on a non-existent stream;
-        // when we cannot make out from the manifest what streams are included in a playlist
-        // we might assume extra streams.
+        // Use min stream duration, but ignore streams that never have any packet
+        // enqueued to prevent us from waiting on a non-existent stream;
+        // when we cannot make out from the manifest what streams are included in
+        // a playlist we might assume extra streams.
+        bufferedDurationUs = -1ll;
         for (size_t i = 0; i < mPacketSources.size(); ++i) {
-            if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0) {
+            if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0
+                    || mPacketSources[i]->getLatestEnqueuedMeta() == NULL) {
                 continue;
             }
 
@@ -642,46 +672,36 @@
                 mPacketSources.valueAt(i)->getBufferedDurationUs(&finalResult);
             ALOGV("buffered %" PRId64 " for stream %d",
                     bufferedStreamDurationUs, mPacketSources.keyAt(i));
-            if (bufferedStreamDurationUs > bufferedDurationUs) {
+            if (bufferedDurationUs == -1ll
+                 || bufferedStreamDurationUs < bufferedDurationUs) {
                 bufferedDurationUs = bufferedStreamDurationUs;
             }
         }
-    }
-    downloadMore = (bufferedDurationUs < durationToBufferUs);
-
-    // signal start if buffered up at least the target size
-    if (!mPrepared && bufferedDurationUs > targetDurationUs && downloadMore) {
-        mPrepared = true;
-
-        ALOGV("prepared, buffered=%" PRId64 " > %" PRId64 "",
-                bufferedDurationUs, targetDurationUs);
-        sp<AMessage> msg = mNotify->dup();
-        msg->setInt32("what", kWhatTemporarilyDoneFetching);
-        msg->post();
+        if (bufferedDurationUs == -1ll) {
+            bufferedDurationUs = 0ll;
+        }
     }
 
-    if (finalResult == OK && downloadMore) {
+    if (finalResult == OK && bufferedDurationUs < kMinBufferedDurationUs) {
         ALOGV("monitoring, buffered=%" PRId64 " < %" PRId64 "",
-                bufferedDurationUs, durationToBufferUs);
+                bufferedDurationUs, kMinBufferedDurationUs);
         // delay the next download slightly; hopefully this gives other concurrent fetchers
         // a better chance to run.
         // onDownloadNext();
-        sp<AMessage> msg = new AMessage(kWhatDownloadNext, id());
+        sp<AMessage> msg = new AMessage(kWhatDownloadNext, this);
         msg->setInt32("generation", mMonitorQueueGeneration);
         msg->post(1000l);
     } else {
-        // Nothing to do yet, try again in a second.
-
-        sp<AMessage> msg = mNotify->dup();
-        msg->setInt32("what", kWhatTemporarilyDoneFetching);
-        msg->post();
-
-        int64_t delayUs = mPrepared ? kMaxMonitorDelayUs : targetDurationUs / 2;
+        // We'd like to maintain buffering above durationToBufferUs, so try
+        // again when buffer just about to go below durationToBufferUs
+        // (or after targetDurationUs / 2, whichever is smaller).
+        int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000ll;
+        if (delayUs > targetDurationUs / 2) {
+            delayUs = targetDurationUs / 2;
+        }
         ALOGV("pausing for %" PRId64 ", buffered=%" PRId64 " > %" PRId64 "",
-                delayUs, bufferedDurationUs, durationToBufferUs);
-        // :TRICKY: need to enforce minimum delay because the delay to
-        // refresh the playlist will become 0
-        postMonitorQueue(delayUs, mPrepared ? targetDurationUs * 2 : 0);
+                delayUs, bufferedDurationUs, kMinBufferedDurationUs);
+        postMonitorQueue(delayUs);
     }
 }
 
@@ -700,8 +720,7 @@
                     mRefreshState = (RefreshState)(mRefreshState + 1);
                 }
             } else {
-                ALOGE("failed to load playlist at url '%s'", mURI.c_str());
-                notifyError(ERROR_IO);
+                ALOGE("failed to load playlist at url '%s'", uriDebugString(mURI).c_str());
                 return ERROR_IO;
             }
         } else {
@@ -724,26 +743,25 @@
 }
 
 void PlaylistFetcher::onDownloadNext() {
-    if (refreshPlaylist() != OK) {
-        return;
-    }
-
-    int32_t firstSeqNumberInPlaylist;
-    if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
-                "media-sequence", &firstSeqNumberInPlaylist)) {
-        firstSeqNumberInPlaylist = 0;
-    }
-
+    status_t err = refreshPlaylist();
+    int32_t firstSeqNumberInPlaylist = 0;
+    int32_t lastSeqNumberInPlaylist = 0;
     bool discontinuity = false;
 
-    const int32_t lastSeqNumberInPlaylist =
-        firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
+    if (mPlaylist != NULL) {
+        if (mPlaylist->meta() != NULL) {
+            mPlaylist->meta()->findInt32("media-sequence", &firstSeqNumberInPlaylist);
+        }
 
-    if (mDiscontinuitySeq < 0) {
-        mDiscontinuitySeq = mPlaylist->getDiscontinuitySeq();
+        lastSeqNumberInPlaylist =
+                firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
+
+        if (mDiscontinuitySeq < 0) {
+            mDiscontinuitySeq = mPlaylist->getDiscontinuitySeq();
+        }
     }
 
-    if (mSeqNumber < 0) {
+    if (mPlaylist != NULL && mSeqNumber < 0) {
         CHECK_GE(mStartTimeUs, 0ll);
 
         if (mSegmentStartTimeUs < 0) {
@@ -754,6 +772,9 @@
                     mSeqNumber = firstSeqNumberInPlaylist;
                 }
             } else {
+                // When seeking mSegmentStartTimeUs is unavailable (< 0), we
+                // use mStartTimeUs (client supplied timestamp) to determine both start segment
+                // and relative position inside a segment
                 mSeqNumber = getSeqNumberForTime(mStartTimeUs);
                 mStartTimeUs -= getSegmentStartTimeUs(mSeqNumber);
             }
@@ -762,6 +783,10 @@
                     mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist,
                     lastSeqNumberInPlaylist);
         } else {
+            // When adapting or track switching, mSegmentStartTimeUs (relative
+            // to media time 0) is used to determine the start segment; mStartTimeUs (absolute
+            // timestamps coming from the media container) is used to determine the position
+            // inside a segments.
             mSeqNumber = getSeqNumberForTime(mSegmentStartTimeUs);
             if (mAdaptive) {
                 // avoid double fetch/decode
@@ -785,19 +810,26 @@
         }
     }
 
+    // if mPlaylist is NULL then err must be non-OK; but the other way around might not be true
     if (mSeqNumber < firstSeqNumberInPlaylist
-            || mSeqNumber > lastSeqNumberInPlaylist) {
-        if (!mPlaylist->isComplete() && mNumRetries < kMaxNumRetries) {
+            || mSeqNumber > lastSeqNumberInPlaylist
+            || err != OK) {
+        if ((err != OK || !mPlaylist->isComplete()) && mNumRetries < kMaxNumRetries) {
             ++mNumRetries;
 
-            if (mSeqNumber > lastSeqNumberInPlaylist) {
+            if (mSeqNumber > lastSeqNumberInPlaylist || err != OK) {
+                // make sure we reach this retry logic on refresh failures
+                // by adding an err != OK clause to all enclosing if's.
+
                 // refresh in increasing fraction (1/2, 1/3, ...) of the
                 // playlist's target duration or 3 seconds, whichever is less
-                int32_t targetDurationSecs;
-                CHECK(mPlaylist->meta()->findInt32(
-                        "target-duration", &targetDurationSecs));
-                int64_t delayUs = mPlaylist->size() * targetDurationSecs *
-                        1000000ll / (1 + mNumRetries);
+                int64_t delayUs = kMaxMonitorDelayUs;
+                if (mPlaylist != NULL && mPlaylist->meta() != NULL) {
+                    int32_t targetDurationSecs;
+                    CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
+                    delayUs = mPlaylist->size() * targetDurationSecs *
+                            1000000ll / (1 + mNumRetries);
+                }
                 if (delayUs > kMaxMonitorDelayUs) {
                     delayUs = kMaxMonitorDelayUs;
                 }
@@ -809,13 +841,30 @@
                 return;
             }
 
-            // we've missed the boat, let's start from the lowest sequence
+            if (err != OK) {
+                notifyError(err);
+                return;
+            }
+
+            // we've missed the boat, let's start 3 segments prior to the latest sequence
             // number available and signal a discontinuity.
 
             ALOGI("We've missed the boat, restarting playback."
                   "  mStartup=%d, was  looking for %d in %d-%d",
                     mStartup, mSeqNumber, firstSeqNumberInPlaylist,
                     lastSeqNumberInPlaylist);
+            if (mStopParams != NULL) {
+                // we should have kept on fetching until we hit the boundaries in mStopParams,
+                // but since the segments we are supposed to fetch have already rolled off
+                // the playlist, i.e. we have already missed the boat, we inevitably have to
+                // skip.
+                for (size_t i = 0; i < mPacketSources.size(); i++) {
+                    sp<ABuffer> formatChange = mSession->createFormatChangeBuffer();
+                    mPacketSources.valueAt(i)->queueAccessUnit(formatChange);
+                }
+                stopAsync(/* clear = */ false);
+                return;
+            }
             mSeqNumber = lastSeqNumberInPlaylist - 3;
             if (mSeqNumber < firstSeqNumberInPlaylist) {
                 mSeqNumber = firstSeqNumberInPlaylist;
@@ -843,11 +892,22 @@
                 &uri,
                 &itemMeta));
 
+    CHECK(itemMeta->findInt32("discontinuity-sequence", &mDiscontinuitySeq));
+
     int32_t val;
     if (itemMeta->findInt32("discontinuity", &val) && val != 0) {
-        mDiscontinuitySeq++;
+        discontinuity = true;
+    } else if (mLastDiscontinuitySeq >= 0
+            && mDiscontinuitySeq != mLastDiscontinuitySeq) {
+        // Seek jumped to a new discontinuity sequence. We need to signal
+        // a format change to decoder. Decoder needs to shutdown and be
+        // created again if seamless format change is unsupported.
+        ALOGV("saw discontinuity: mStartup %d, mLastDiscontinuitySeq %d, "
+                "mDiscontinuitySeq %d, mStartTimeUs %lld",
+            mStartup, mLastDiscontinuitySeq, mDiscontinuitySeq, (long long)mStartTimeUs);
         discontinuity = true;
     }
+    mLastDiscontinuitySeq = -1;
 
     int64_t range_offset, range_length;
     if (!itemMeta->findInt64("range-offset", &range_offset)
@@ -876,13 +936,68 @@
         }
     }
 
+    if ((mStartup && !mTimeChangeSignaled) || discontinuity) {
+        // We need to signal a time discontinuity to ATSParser on the
+        // first segment after start, or on a discontinuity segment.
+        // Setting mNextPTSTimeUs informs extractAndQueueAccessUnitsXX()
+        // to send the time discontinuity.
+        if (mPlaylist->isComplete() || mPlaylist->isEvent()) {
+            // If this was a live event this made no sense since
+            // we don't have access to all the segment before the current
+            // one.
+            mNextPTSTimeUs = getSegmentStartTimeUs(mSeqNumber);
+        }
+
+        // Setting mTimeChangeSignaled to true, so that if start time
+        // searching goes into 2nd segment (without a discontinuity),
+        // we don't reset time again. It causes corruption when pending
+        // data in ATSParser is cleared.
+        mTimeChangeSignaled = true;
+    }
+
+    if (discontinuity) {
+        ALOGI("queueing discontinuity (explicit=%d)", discontinuity);
+
+        // Signal a format discontinuity to ATSParser to clear partial data
+        // from previous streams. Not doing this causes bitstream corruption.
+        mTSParser->signalDiscontinuity(
+                ATSParser::DISCONTINUITY_FORMATCHANGE, NULL /* extra */);
+
+        queueDiscontinuity(
+                ATSParser::DISCONTINUITY_FORMATCHANGE,
+                NULL /* extra */);
+
+        if (mStartup && mStartTimeUsRelative && mFirstPTSValid) {
+            // This means we guessed mStartTimeUs to be in the previous
+            // segment (likely very close to the end), but either video or
+            // audio has not found start by the end of that segment.
+            //
+            // If this new segment is not a discontinuity, keep searching.
+            //
+            // If this new segment even got a discontinuity marker, just
+            // set mStartTimeUs=0, and take all samples from now on.
+            mStartTimeUs = 0;
+            mFirstPTSValid = false;
+        }
+    }
+
     // block-wise download
-    bool startup = mStartup;
     ssize_t bytesRead;
     do {
+        int64_t startUs = ALooper::GetNowUs();
+
         bytesRead = mSession->fetchFile(
                 uri.c_str(), &buffer, range_offset, range_length, kDownloadBlockSize, &source);
 
+        // add sample for bandwidth estimation (excluding subtitles)
+        if (bytesRead > 0
+                && (mStreamTypeMask
+                        & (LiveSession::STREAMTYPE_AUDIO
+                        | LiveSession::STREAMTYPE_VIDEO))) {
+            int64_t delayUs = ALooper::GetNowUs() - startUs;
+            mSession->addBandwidthMeasurement(bytesRead, delayUs);
+        }
+
         if (bytesRead < 0) {
             status_t err = bytesRead;
             ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
@@ -907,29 +1022,6 @@
             return;
         }
 
-        if (startup || discontinuity) {
-            // Signal discontinuity.
-
-            if (mPlaylist->isComplete() || mPlaylist->isEvent()) {
-                // If this was a live event this made no sense since
-                // we don't have access to all the segment before the current
-                // one.
-                mNextPTSTimeUs = getSegmentStartTimeUs(mSeqNumber);
-            }
-
-            if (discontinuity) {
-                ALOGI("queueing discontinuity (explicit=%d)", discontinuity);
-
-                queueDiscontinuity(
-                        ATSParser::DISCONTINUITY_FORMATCHANGE,
-                        NULL /* extra */);
-
-                discontinuity = false;
-            }
-
-            startup = false;
-        }
-
         err = OK;
         if (bufferStartsWithTsSyncByte(buffer)) {
             // Incremental extraction is only supported for MPEG2 transport streams.
@@ -949,6 +1041,10 @@
         if (err == -EAGAIN) {
             // starting sequence number too low/high
             mTSParser.clear();
+            for (size_t i = 0; i < mPacketSources.size(); i++) {
+                sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
+                packetSource->clear();
+            }
             postMonitorQueue();
             return;
         } else if (err == ERROR_OUT_OF_RANGE) {
@@ -960,11 +1056,11 @@
             return;
         }
 
-    } while (bytesRead != 0);
+    } while (bytesRead != 0 && !mStopping);
 
     if (bufferStartsWithTsSyncByte(buffer)) {
-        // If we still don't see a stream after fetching a full ts segment mark it as
-        // nonexistent.
+        // If we don't see a stream in the program table after fetching a full ts segment
+        // mark it as nonexistent.
         const size_t kNumTypes = ATSParser::NUM_SOURCE_TYPES;
         ATSParser::SourceType srcTypes[kNumTypes] =
                 { ATSParser::VIDEO, ATSParser::AUDIO };
@@ -979,7 +1075,7 @@
                 static_cast<AnotherPacketSource *>(
                     mTSParser->getSource(srcType).get());
 
-            if (source == NULL) {
+            if (!mTSParser->hasSource(srcType)) {
                 ALOGW("MPEG2 Transport stream does not contain %s data.",
                       srcType == ATSParser::VIDEO ? "video" : "audio");
 
@@ -996,7 +1092,7 @@
         return;
     }
 
-    status_t err = OK;
+    err = OK;
     if (tsBuffer != NULL) {
         AString method;
         CHECK(buffer->meta()->findString("cipher-method", &method));
@@ -1137,6 +1233,11 @@
         accessUnit->meta()->setInt32("discard", discard);
     }
 
+    int32_t targetDurationSecs;
+    if (mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)) {
+        accessUnit->meta()->setInt32("targetDuration", targetDurationSecs);
+    }
+
     accessUnit->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq);
     accessUnit->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber));
     return accessUnit;
@@ -1157,9 +1258,7 @@
         mTSParser->signalDiscontinuity(
                 ATSParser::DISCONTINUITY_TIME, extra);
 
-        mAbsoluteTimeAnchorUs = mNextPTSTimeUs;
         mNextPTSTimeUs = -1ll;
-        mFirstPTSValid = false;
     }
 
     size_t offset = 0;
@@ -1212,12 +1311,17 @@
             continue;
         }
 
-        int64_t timeUs;
+        const char *mime;
+        sp<MetaData> format  = source->getFormat();
+        bool isAvc = format != NULL && format->findCString(kKeyMIMEType, &mime)
+                && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
+
         sp<ABuffer> accessUnit;
         status_t finalResult;
         while (source->hasBufferAvailable(&finalResult)
                 && source->dequeueAccessUnit(&accessUnit) == OK) {
 
+            int64_t timeUs;
             CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
 
             if (mStartup) {
@@ -1232,30 +1336,30 @@
                     }
                 }
 
-                if (timeUs < mStartTimeUs) {
+                if (timeUs < mStartTimeUs || (isAvc && !mIDRFound)) {
                     // buffer up to the closest preceding IDR frame
                     ALOGV("timeUs %" PRId64 " us < mStartTimeUs %" PRId64 " us",
                             timeUs, mStartTimeUs);
-                    const char *mime;
-                    sp<MetaData> format  = source->getFormat();
-                    bool isAvc = false;
-                    if (format != NULL && format->findCString(kKeyMIMEType, &mime)
-                            && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
-                        isAvc = true;
-                    }
-                    if (isAvc && IsIDR(accessUnit)) {
-                        mVideoBuffer->clear();
-                    }
                     if (isAvc) {
-                        mVideoBuffer->queueAccessUnit(accessUnit);
+                        if (IsIDR(accessUnit)) {
+                            mVideoBuffer->clear();
+                            mIDRFound = true;
+                        }
+                        if (mIDRFound) {
+                            mVideoBuffer->queueAccessUnit(accessUnit);
+                        }
                     }
 
                     continue;
                 }
             }
 
-            CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
-            if (mStartTimeUsNotify != NULL && timeUs > mStartTimeUs) {
+            if (mStartTimeUsNotify != NULL) {
+                int32_t firstSeqNumberInPlaylist;
+                if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
+                            "media-sequence", &firstSeqNumberInPlaylist)) {
+                    firstSeqNumberInPlaylist = 0;
+                }
 
                 int32_t targetDurationSecs;
                 CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
@@ -1266,6 +1370,8 @@
                 //   mStartTimeUs.
                 // mSegmentStartTimeUs >= 0
                 //   mSegmentStartTimeUs is non-negative when adapting or switching tracks
+                // mSeqNumber > firstSeqNumberInPlaylist
+                //   don't decrement mSeqNumber if it already points to the 1st segment
                 // timeUs - mStartTimeUs > targetDurationUs:
                 //   This and the 2 above conditions should only happen when adapting in a live
                 //   stream; the old fetcher has already fetched to mStartTimeUs; the new fetcher
@@ -1275,6 +1381,7 @@
                 //   stop as early as possible. The definition of being "too far ahead" is
                 //   arbitrary; here we use targetDurationUs as threshold.
                 if (mStartup && mSegmentStartTimeUs >= 0
+                        && mSeqNumber > firstSeqNumberInPlaylist
                         && timeUs - mStartTimeUs > targetDurationUs) {
                     // we just guessed a starting timestamp that is too high when adapting in a
                     // live stream; re-adjust based on the actual timestamp extracted from the
@@ -1416,8 +1523,6 @@
     }
 
     if (mNextPTSTimeUs >= 0ll) {
-        mFirstPTSValid = false;
-        mAbsoluteTimeAnchorUs = mNextPTSTimeUs;
         mNextPTSTimeUs = -1ll;
     }
 
@@ -1495,7 +1600,7 @@
 
         CHECK_EQ(bits.getBits(12), 0xfffu);
         bits.skipBits(3);  // ID, layer
-        bool protection_absent = bits.getBits(1) != 0;
+        bool protection_absent __unused = bits.getBits(1) != 0;
 
         unsigned profile = bits.getBits(2);
         CHECK_NE(profile, 3u);
@@ -1518,7 +1623,7 @@
     CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
 
     int64_t timeUs = (PTS * 100ll) / 9ll;
-    if (!mFirstPTSValid) {
+    if (mStartup && !mFirstPTSValid) {
         mFirstPTSValid = true;
         mFirstTimeUs = timeUs;
     }
@@ -1587,6 +1692,7 @@
                 mStartTimeUsNotify->setInt32("streamMask", LiveSession::STREAMTYPE_AUDIO);
                 mStartTimeUsNotify->post();
                 mStartTimeUsNotify.clear();
+                mStartup = false;
             }
         }
 
@@ -1635,33 +1741,4 @@
     msg->post();
 }
 
-int64_t PlaylistFetcher::resumeThreshold(const sp<AMessage> &msg) {
-    int64_t durationUs, threshold;
-    if (msg->findInt64("durationUs", &durationUs)) {
-        return kNumSkipFrames * durationUs;
-    }
-
-    sp<RefBase> obj;
-    msg->findObject("format", &obj);
-    MetaData *format = static_cast<MetaData *>(obj.get());
-
-    const char *mime;
-    CHECK(format->findCString(kKeyMIMEType, &mime));
-    bool audio = !strncasecmp(mime, "audio/", 6);
-    if (audio) {
-        // Assumes 1000 samples per frame.
-        int32_t sampleRate;
-        CHECK(format->findInt32(kKeySampleRate, &sampleRate));
-        return kNumSkipFrames  /* frames */ * 1000 /* samples */
-                * (1000000 / sampleRate) /* sample duration (us) */;
-    } else {
-        int32_t frameRate;
-        if (format->findInt32(kKeyFrameRate, &frameRate) && frameRate > 0) {
-            return kNumSkipFrames * (1000000 / frameRate);
-        }
-    }
-
-    return 500000ll;
-}
-
 }  // namespace android
diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h
index 78c358f..b82e50d 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.h
+++ b/media/libstagefright/httplive/PlaylistFetcher.h
@@ -31,16 +31,19 @@
 struct HTTPBase;
 struct LiveDataSource;
 struct M3UParser;
-struct String8;
+class String8;
 
 struct PlaylistFetcher : public AHandler {
+    static const int64_t kMinBufferedDurationUs;
+    static const int32_t kDownloadBlockSize;
+    static const int64_t kFetcherResumeThreshold;
+
     enum {
         kWhatStarted,
         kWhatPaused,
         kWhatStopped,
         kWhatError,
         kWhatDurationUpdate,
-        kWhatTemporarilyDoneFetching,
         kWhatPrepared,
         kWhatPreparationFailed,
         kWhatStartedAt,
@@ -64,7 +67,7 @@
             int32_t startDiscontinuitySeq = 0,
             bool adaptive = false);
 
-    void pauseAsync();
+    void pauseAsync(bool immediate = false);
 
     void stopAsync(bool clear = true);
 
@@ -92,9 +95,7 @@
         kWhatDownloadNext   = 'dlnx',
     };
 
-    static const int64_t kMinBufferedDurationUs;
     static const int64_t kMaxMonitorDelayUs;
-    static const int32_t kDownloadBlockSize;
     static const int32_t kNumSkipFrames;
 
     static bool bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer);
@@ -115,7 +116,7 @@
     // adapting or switching tracks.
     int64_t mSegmentStartTimeUs;
 
-    ssize_t mDiscontinuitySeq;
+    int32_t mDiscontinuitySeq;
     bool mStartTimeUsRelative;
     sp<AMessage> mStopParams; // message containing the latest timestamps we should fetch.
 
@@ -129,13 +130,20 @@
     int32_t mSeqNumber;
     int32_t mNumRetries;
     bool mStartup;
+    bool mIDRFound;
     bool mAdaptive;
     bool mPrepared;
+    bool mTimeChangeSignaled;
     int64_t mNextPTSTimeUs;
 
     int32_t mMonitorQueueGeneration;
     const int32_t mSubtitleGeneration;
 
+    int32_t mLastDiscontinuitySeq;
+
+    Mutex mStoppingLock;
+    bool mStopping;
+
     enum RefreshState {
         INITIAL_MINIMUM_RELOAD_DELAY,
         FIRST_UNCHANGED_RELOAD_ATTEMPT,
@@ -151,7 +159,6 @@
     bool mFirstPTSValid;
     uint64_t mFirstPTS;
     int64_t mFirstTimeUs;
-    int64_t mAbsoluteTimeAnchorUs;
     sp<AnotherPacketSource> mVideoBuffer;
 
     // Stores the initialization vector to decrypt the next block of cipher text, which can
@@ -174,6 +181,7 @@
 
     void postMonitorQueue(int64_t delayUs = 0, int64_t minDelayUs = 0);
     void cancelMonitorQueue();
+    void setStopping(bool stopping);
 
     int64_t delayUsToRefreshPlaylist() const;
     status_t refreshPlaylist();
@@ -211,10 +219,6 @@
 
     void updateDuration();
 
-    // Before resuming a fetcher in onResume, check the remaining duration is longer than that
-    // returned by resumeThreshold.
-    int64_t resumeThreshold(const sp<AMessage> &msg);
-
     DISALLOW_EVIL_CONSTRUCTORS(PlaylistFetcher);
 };
 
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 7f221a0..d9491d6 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -630,7 +630,10 @@
                 | (mParent.mData[mOffset + 4] << 8)
                 | mParent.mData[mOffset + 5];
 
-            mFrameSize += 6;
+            if (mFrameSize == 0) {
+                return;
+            }
+            mFrameSize += 6; // add tag id and size field
 
             if (mOffset + mFrameSize > mParent.mSize) {
                 ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
@@ -671,7 +674,11 @@
                 baseSize = U32_AT(&mParent.mData[mOffset + 4]);
             }
 
-            mFrameSize = 10 + baseSize;
+            if (baseSize == 0) {
+                return;
+            }
+
+            mFrameSize = 10 + baseSize; // add tag id, size field and flags
 
             if (mOffset + mFrameSize > mParent.mSize) {
                 ALOGV("partial frame at offset %zu (size = %zu, bytes-remaining = %zu)",
@@ -793,8 +800,8 @@
             mime->setTo((const char *)&data[1]);
             size_t mimeLen = strlen((const char *)&data[1]) + 1;
 
-            uint8_t picType = data[1 + mimeLen];
 #if 0
+            uint8_t picType = data[1 + mimeLen];
             if (picType != 0x03) {
                 // Front Cover Art
                 it.next();
diff --git a/media/libstagefright/include/AACEncoder.h b/media/libstagefright/include/AACEncoder.h
index 3d5fc60..52beb0e 100644
--- a/media/libstagefright/include/AACEncoder.h
+++ b/media/libstagefright/include/AACEncoder.h
@@ -25,7 +25,7 @@
 
 namespace android {
 
-struct MediaBufferGroup;
+class MediaBufferGroup;
 
 class AACEncoder: public MediaSource {
     public:
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
index 1c3cd5e..0c66e27 100644
--- a/media/libstagefright/include/HTTPBase.h
+++ b/media/libstagefright/include/HTTPBase.h
@@ -48,6 +48,8 @@
 
     virtual status_t setBandwidthStatCollectFreq(int32_t freqMs);
 
+    virtual void setBandwidthHistorySize(size_t numHistoryItems);
+
     static void RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag);
     static void UnRegisterSocketUserTag(int sockfd);
 
@@ -55,7 +57,7 @@
     static void UnRegisterSocketUserMark(int sockfd);
 
 protected:
-    void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
+    virtual void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
 
 private:
     struct BandwidthEntry {
@@ -69,6 +71,7 @@
     size_t mNumBandwidthHistoryItems;
     int64_t mTotalTransferTimeUs;
     size_t mTotalTransferBytes;
+    size_t mMaxBandwidthHistoryItems;
 
     enum {
         kMinBandwidthCollectFreqMs = 1000,   // 1 second
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index e83f3ef..c2c4a6d 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -22,8 +22,8 @@
 
 namespace android {
 
-struct DataSource;
-struct String8;
+class DataSource;
+class String8;
 
 struct ID3 {
     enum Version {
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
index c5e86a6..db1187d 100644
--- a/media/libstagefright/include/MPEG2TSExtractor.h
+++ b/media/libstagefright/include/MPEG2TSExtractor.h
@@ -28,7 +28,7 @@
 struct AMessage;
 struct AnotherPacketSource;
 struct ATSParser;
-struct DataSource;
+class DataSource;
 struct MPEG2TSSource;
 struct String8;
 
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 1fe6fcf..8c16251 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -83,6 +83,8 @@
 
     Vector<SidxEntry> mSidxEntries;
     off64_t mMoofOffset;
+    bool mMoofFound;
+    bool mMdatFound;
 
     Vector<PsshInfo> mPssh;
 
diff --git a/media/libstagefright/include/MidiExtractor.h b/media/libstagefright/include/MidiExtractor.h
new file mode 100644
index 0000000..9a2abc0
--- /dev/null
+++ b/media/libstagefright/include/MidiExtractor.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2014 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 MIDI_EXTRACTOR_H_
+#define MIDI_EXTRACTOR_H_
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/MidiIoWrapper.h>
+#include <utils/String8.h>
+#include <libsonivox/eas.h>
+
+namespace android {
+
+class MidiEngine : public RefBase {
+public:
+    MidiEngine(const sp<DataSource> &dataSource,
+            const sp<MetaData> &fileMetadata,
+            const sp<MetaData> &trackMetadata);
+    ~MidiEngine();
+
+    status_t initCheck();
+
+    status_t allocateBuffers();
+    status_t releaseBuffers();
+    status_t seekTo(int64_t positionUs);
+    MediaBuffer* readBuffer();
+private:
+    sp<MidiIoWrapper> mIoWrapper;
+    MediaBufferGroup *mGroup;
+    EAS_DATA_HANDLE mEasData;
+    EAS_HANDLE mEasHandle;
+    const S_EAS_LIB_CONFIG* mEasConfig;
+    bool mIsInitialized;
+};
+
+class MidiExtractor : public MediaExtractor {
+
+public:
+    // Extractor assumes ownership of source
+    MidiExtractor(const sp<DataSource> &source);
+
+    virtual size_t countTracks();
+    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+
+    virtual sp<MetaData> getMetaData();
+
+protected:
+    virtual ~MidiExtractor();
+
+private:
+    sp<DataSource> mDataSource;
+    status_t mInitCheck;
+    sp<MetaData> mFileMetadata;
+
+    // There is only one track
+    sp<MetaData> mTrackMetadata;
+
+    sp<MidiEngine> mEngine;
+
+    EAS_DATA_HANDLE     mEasData;
+    EAS_HANDLE          mEasHandle;
+    EAS_PCM*            mAudioBuffer;
+    EAS_I32             mPlayTime;
+    EAS_I32             mDuration;
+    EAS_STATE           mState;
+    EAS_FILE            mFileLocator;
+
+    MidiExtractor(const MidiExtractor &);
+    MidiExtractor &operator=(const MidiExtractor &);
+
+};
+
+bool SniffMidi(const sp<DataSource> &source, String8 *mimeType,
+        float *confidence, sp<AMessage> *);
+
+}  // namespace android
+
+#endif  // MIDI_EXTRACTOR_H_
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 24d431c..104dcfc 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -31,7 +31,7 @@
 
 struct OMXNodeInstance {
     OMXNodeInstance(
-            OMX *owner, const sp<IOMXObserver> &observer);
+            OMX *owner, const sp<IOMXObserver> &observer, const char *name);
 
     void setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle);
 
@@ -149,6 +149,18 @@
     KeyedVector<OMX_BUFFERHEADERTYPE *, OMX::buffer_id> mBufferHeaderToBufferID;
 #endif
 
+    // For debug support
+    char *mName;
+    int DEBUG;
+    size_t mNumPortBuffers[2];  // modified under mLock, read outside for debug
+    Mutex mDebugLock;
+    // following are modified and read under mDebugLock
+    int DEBUG_BUMP;
+    SortedVector<OMX_BUFFERHEADERTYPE *> mInputBuffersWithCodec, mOutputBuffersWithCodec;
+    size_t mDebugLevelBumpPendingBuffers[2];
+    void bumpDebugLevel_l(size_t numInputBuffers, size_t numOutputBuffers);
+    void unbumpDebugLevel_l(size_t portIndex);
+
     ~OMXNodeInstance();
 
     void addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id);
@@ -186,6 +198,10 @@
             OMX_U32 portIndex, OMX_BOOL enable,
             OMX_BOOL useGraphicBuffer, OMX_BOOL *usingGraphicBufferInMeta);
 
+    status_t emptyBuffer_l(
+            OMX_BUFFERHEADERTYPE *header,
+            OMX_U32 flags, OMX_TICKS timestamp, intptr_t debugAddr);
+
     sp<GraphicBufferSource> getGraphicBufferSource();
     void setGraphicBufferSource(const sp<GraphicBufferSource>& bufferSource);
 
diff --git a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
index 9e97ebd..4529007 100644
--- a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
+++ b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
@@ -61,9 +61,10 @@
     void initPorts(OMX_U32 numInputBuffers,
             OMX_U32 inputBufferSize,
             OMX_U32 numOutputBuffers,
-            const char *mimeType);
+            const char *mimeType,
+            OMX_U32 minCompressionRatio = 1u);
 
-    virtual void updatePortDefinitions(bool updateCrop = true);
+    virtual void updatePortDefinitions(bool updateCrop = true, bool updateInputSize = false);
 
     uint32_t outputBufferWidth();
     uint32_t outputBufferHeight();
@@ -99,6 +100,9 @@
     } mOutputPortSettingsChange;
 
 private:
+    uint32_t mMinInputBufferSize;
+    uint32_t mMinCompressionRatio;
+
     const char *mComponentRole;
     OMX_VIDEO_CODINGTYPE mCodingType;
     const CodecProfileLevel *mProfileLevels;
diff --git a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h b/media/libstagefright/include/SoftVideoEncoderOMXComponent.h
index b3b810d..b43635d 100644
--- a/media/libstagefright/include/SoftVideoEncoderOMXComponent.h
+++ b/media/libstagefright/include/SoftVideoEncoderOMXComponent.h
@@ -18,6 +18,8 @@
 
 #define SOFT_VIDEO_ENCODER_OMX_COMPONENT_H_
 
+#include <media/IOMX.h>
+
 #include "SimpleSoftOMXComponent.h"
 #include <system/window.h>
 
@@ -28,11 +30,26 @@
 struct SoftVideoEncoderOMXComponent : public SimpleSoftOMXComponent {
     SoftVideoEncoderOMXComponent(
             const char *name,
+            const char *componentRole,
+            OMX_VIDEO_CODINGTYPE codingType,
+            const CodecProfileLevel *profileLevels,
+            size_t numProfileLevels,
+            int32_t width,
+            int32_t height,
             const OMX_CALLBACKTYPE *callbacks,
             OMX_PTR appData,
             OMX_COMPONENTTYPE **component);
 
+    virtual OMX_ERRORTYPE internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR param);
+    virtual OMX_ERRORTYPE internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params);
+
 protected:
+    void initPorts(
+            OMX_U32 numInputBuffers, OMX_U32 numOutputBuffers, OMX_U32 outputBufferSize,
+            const char *mime, OMX_U32 minCompressionRatio = 1);
+
+    static void setRawVideoSize(OMX_PARAM_PORTDEFINITIONTYPE *def);
+
     static void ConvertFlexYUVToPlanar(
             uint8_t *dst, size_t dstStride, size_t dstVStride,
             struct android_ycbcr *ycbcr, int32_t width, int32_t height);
@@ -56,9 +73,30 @@
         kOutputPortIndex = 1,
     };
 
+    bool mInputDataIsMeta;
+    int32_t mWidth;      // width of the input frames
+    int32_t mHeight;     // height of the input frames
+    uint32_t mBitrate;   // target bitrate set for the encoder, in bits per second
+    uint32_t mFramerate; // target framerate set for the encoder, in Q16 format
+    OMX_COLOR_FORMATTYPE mColorFormat;  // Color format for the input port
+
 private:
+    void updatePortParams();
+    OMX_ERRORTYPE internalSetPortParams(const OMX_PARAM_PORTDEFINITIONTYPE* port);
+
+    static const uint32_t kInputBufferAlignment = 1;
+    static const uint32_t kOutputBufferAlignment = 2;
+
     mutable const hw_module_t *mGrallocModule;
 
+    uint32_t mMinOutputBufferSize;
+    uint32_t mMinCompressionRatio;
+
+    const char *mComponentRole;
+    OMX_VIDEO_CODINGTYPE mCodingType;
+    const CodecProfileLevel *mProfileLevels;
+    size_t mNumProfileLevels;
+
     DISALLOW_EVIL_CONSTRUCTORS(SoftVideoEncoderOMXComponent);
 };
 
diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h
index d517320..dafa07e 100644
--- a/media/libstagefright/include/avc_utils.h
+++ b/media/libstagefright/include/avc_utils.h
@@ -23,7 +23,7 @@
 
 namespace android {
 
-struct ABitReader;
+class ABitReader;
 
 enum {
     kAVCProfileBaseline      = 0x42,
@@ -36,6 +36,11 @@
     kAVCProfileCAVLC444Intra = 0x2c
 };
 
+struct NALPosition {
+    size_t nalOffset;
+    size_t nalSize;
+};
+
 // Optionally returns sample aspect ratio as well.
 void FindAVCDimensions(
         const sp<ABuffer> &seqParamSet,
@@ -49,7 +54,7 @@
         const uint8_t **nalStart, size_t *nalSize,
         bool startCodeFollows = false);
 
-struct MetaData;
+class MetaData;
 sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit);
 
 bool IsIDR(const sp<ABuffer> &accessUnit);
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 2587ec7..0712bf0 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -413,16 +413,16 @@
 
     const mkvparser::CuePoint* pCP;
     mkvparser::Tracks const *pTracks = pSegment->GetTracks();
-    unsigned long int trackCount = pTracks->GetTracksCount();
     while (!pCues->DoneParsing()) {
         pCues->LoadCuePoint();
         pCP = pCues->GetLast();
         CHECK(pCP);
 
+        size_t trackCount = mExtractor->mTracks.size();
         for (size_t index = 0; index < trackCount; ++index) {
-            const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index);
+            MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index);
+            const mkvparser::Track *pTrack = pTracks->GetTrackByNumber(track.mTrackNum);
             if (pTrack && pTrack->GetType() == 1 && pCP->Find(pTrack)) { // VIDEO_TRACK
-                MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(index);
                 track.mCuePoints.push_back(pCP);
             }
         }
@@ -434,12 +434,13 @@
     }
 
     const mkvparser::CuePoint::TrackPosition *pTP = NULL;
-    const mkvparser::Track *thisTrack = pTracks->GetTrackByIndex(mIndex);
+    const mkvparser::Track *thisTrack = pTracks->GetTrackByNumber(mTrackNum);
     if (thisTrack->GetType() == 1) { // video
         MatroskaExtractor::TrackInfo& track = mExtractor->mTracks.editItemAt(mIndex);
         pTP = track.find(seekTimeNs);
     } else {
         // The Cue index is built around video keyframes
+        unsigned long int trackCount = pTracks->GetTracksCount();
         for (size_t index = 0; index < trackCount; ++index) {
             const mkvparser::Track *pTrack = pTracks->GetTrackByIndex(index);
             if (pTrack && pTrack->GetType() == 1 && pCues->Find(seekTimeNs, pTrack, pCP, pTP)) {
@@ -499,17 +500,6 @@
     return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
 }
 
-static size_t clz(uint8_t x) {
-    size_t numLeadingZeroes = 0;
-
-    while (!(x & 0x80)) {
-        ++numLeadingZeroes;
-        x = x << 1;
-    }
-
-    return numLeadingZeroes;
-}
-
 void MatroskaSource::clearPendingFrames() {
     while (!mPendingFrames.empty()) {
         MediaBuffer *frame = *mPendingFrames.begin();
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index eab7616..6786506 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -35,6 +35,7 @@
 #include <media/stagefright/Utils.h>
 #include <media/IStreamSource.h>
 #include <utils/KeyedVector.h>
+#include <utils/Vector.h>
 
 #include <inttypes.h>
 
@@ -63,6 +64,7 @@
     void signalEOS(status_t finalResult);
 
     sp<MediaSource> getSource(SourceType type);
+    bool hasSource(SourceType type) const;
 
     int64_t convertPTSToTimestamp(uint64_t PTS);
 
@@ -85,14 +87,22 @@
     }
 
 private:
+    struct StreamInfo {
+        unsigned mType;
+        unsigned mPID;
+    };
+
     ATSParser *mParser;
     unsigned mProgramNumber;
     unsigned mProgramMapPID;
     KeyedVector<unsigned, sp<Stream> > mStreams;
     bool mFirstPTSValid;
     uint64_t mFirstPTS;
+    int64_t mLastRecoveredPTS;
 
     status_t parseProgramMap(ABitReader *br);
+    int64_t recoverPTS(uint64_t PTS_33bit);
+    bool switchPIDs(const Vector<StreamInfo> &infos);
 
     DISALLOW_EVIL_CONSTRUCTORS(Program);
 };
@@ -119,6 +129,9 @@
 
     sp<MediaSource> getSource(SourceType type);
 
+    bool isAudio() const;
+    bool isVideo() const;
+
 protected:
     virtual ~Stream();
 
@@ -146,9 +159,6 @@
 
     void extractAACFrames(const sp<ABuffer> &buffer);
 
-    bool isAudio() const;
-    bool isVideo() const;
-
     DISALLOW_EVIL_CONSTRUCTORS(Stream);
 };
 
@@ -181,7 +191,8 @@
       mProgramNumber(programNumber),
       mProgramMapPID(programMapPID),
       mFirstPTSValid(false),
-      mFirstPTS(0) {
+      mFirstPTS(0),
+      mLastRecoveredPTS(-1ll) {
     ALOGV("new program number %u", programNumber);
 }
 
@@ -236,10 +247,71 @@
     }
 }
 
-struct StreamInfo {
-    unsigned mType;
-    unsigned mPID;
-};
+bool ATSParser::Program::switchPIDs(const Vector<StreamInfo> &infos) {
+    bool success = false;
+
+    if (mStreams.size() == infos.size()) {
+        // build type->PIDs map for old and new mapping
+        size_t i;
+        KeyedVector<int32_t, Vector<int32_t> > oldType2PIDs, newType2PIDs;
+        for (i = 0; i < mStreams.size(); ++i) {
+            ssize_t index = oldType2PIDs.indexOfKey(mStreams[i]->type());
+            if (index < 0) {
+                oldType2PIDs.add(mStreams[i]->type(), Vector<int32_t>());
+            }
+            oldType2PIDs.editValueFor(mStreams[i]->type()).push_back(mStreams[i]->pid());
+        }
+        for (i = 0; i < infos.size(); ++i) {
+            ssize_t index = newType2PIDs.indexOfKey(infos[i].mType);
+            if (index < 0) {
+                newType2PIDs.add(infos[i].mType, Vector<int32_t>());
+            }
+            newType2PIDs.editValueFor(infos[i].mType).push_back(infos[i].mPID);
+        }
+
+        // we can recover if the number of streams for each type hasn't changed
+        if (oldType2PIDs.size() == newType2PIDs.size()) {
+            success = true;
+            for (i = 0; i < oldType2PIDs.size(); ++i) {
+                // KeyedVector is sorted, we just compare key and size of each index
+                if (oldType2PIDs.keyAt(i) != newType2PIDs.keyAt(i)
+                        || oldType2PIDs[i].size() != newType2PIDs[i].size()) {
+                     success = false;
+                     break;
+                }
+            }
+        }
+
+        if (success) {
+            // save current streams to temp
+            KeyedVector<int32_t, sp<Stream> > temp;
+            for (i = 0; i < mStreams.size(); ++i) {
+                 temp.add(mStreams.keyAt(i), mStreams.editValueAt(i));
+            }
+
+            mStreams.clear();
+            for (i = 0; i < temp.size(); ++i) {
+                // The two checks below shouldn't happen,
+                // we already checked above the stream count matches
+                ssize_t index = newType2PIDs.indexOfKey(temp[i]->type());
+                CHECK(index >= 0);
+                Vector<int32_t> &newPIDs = newType2PIDs.editValueAt(index);
+                CHECK(newPIDs.size() > 0);
+
+                // get the next PID for temp[i]->type() in the new PID map
+                Vector<int32_t>::iterator it = newPIDs.begin();
+
+                // change the PID of the stream, and add it back
+                temp.editValueAt(i)->setPID(*it);
+                mStreams.add(temp[i]->pid(), temp.editValueAt(i));
+
+                // removed the used PID
+                newPIDs.erase(it);
+            }
+        }
+    }
+    return success;
+}
 
 status_t ATSParser::Program::parseProgramMap(ABitReader *br) {
     unsigned table_id = br->getBits(8);
@@ -368,39 +440,8 @@
         }
 #endif
 
-        // The only case we can recover from is if we have two streams
-        // and they switched PIDs.
-
-        bool success = false;
-
-        if (mStreams.size() == 2 && infos.size() == 2) {
-            const StreamInfo &info1 = infos.itemAt(0);
-            const StreamInfo &info2 = infos.itemAt(1);
-
-            sp<Stream> s1 = mStreams.editValueAt(0);
-            sp<Stream> s2 = mStreams.editValueAt(1);
-
-            bool caseA =
-                info1.mPID == s1->pid() && info1.mType == s2->type()
-                    && info2.mPID == s2->pid() && info2.mType == s1->type();
-
-            bool caseB =
-                info1.mPID == s2->pid() && info1.mType == s1->type()
-                    && info2.mPID == s1->pid() && info2.mType == s2->type();
-
-            if (caseA || caseB) {
-                unsigned pid1 = s1->pid();
-                unsigned pid2 = s2->pid();
-                s1->setPID(pid2);
-                s2->setPID(pid1);
-
-                mStreams.clear();
-                mStreams.add(s1->pid(), s1);
-                mStreams.add(s2->pid(), s2);
-
-                success = true;
-            }
-        }
+        // we can recover if number of streams for each type remain the same
+        bool success = switchPIDs(infos);
 
         if (!success) {
             ALOGI("Stream PIDs changed and we cannot recover.");
@@ -424,6 +465,32 @@
     return OK;
 }
 
+int64_t ATSParser::Program::recoverPTS(uint64_t PTS_33bit) {
+    // We only have the lower 33-bit of the PTS. It could overflow within a
+    // reasonable amount of time. To handle the wrap-around, use fancy math
+    // to get an extended PTS that is within [-0xffffffff, 0xffffffff]
+    // of the latest recovered PTS.
+    if (mLastRecoveredPTS < 0ll) {
+        // Use the original 33bit number for 1st frame, the reason is that
+        // if 1st frame wraps to negative that's far away from 0, we could
+        // never start. Only start wrapping around from 2nd frame.
+        mLastRecoveredPTS = static_cast<int64_t>(PTS_33bit);
+    } else {
+        mLastRecoveredPTS = static_cast<int64_t>(
+                ((mLastRecoveredPTS - PTS_33bit + 0x100000000ll)
+                & 0xfffffffe00000000ull) | PTS_33bit);
+        // We start from 0, but recovered PTS could be slightly below 0.
+        // Clamp it to 0 as rest of the pipeline doesn't take negative pts.
+        // (eg. video is read first and starts at 0, but audio starts at 0xfffffff0)
+        if (mLastRecoveredPTS < 0ll) {
+            ALOGI("Clamping negative recovered PTS (%" PRId64 ") to 0", mLastRecoveredPTS);
+            mLastRecoveredPTS = 0ll;
+        }
+    }
+
+    return mLastRecoveredPTS;
+}
+
 sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
     size_t index = (type == AUDIO) ? 0 : 0;
 
@@ -440,7 +507,22 @@
     return NULL;
 }
 
+bool ATSParser::Program::hasSource(SourceType type) const {
+    for (size_t i = 0; i < mStreams.size(); ++i) {
+        const sp<Stream> &stream = mStreams.valueAt(i);
+        if (type == AUDIO && stream->isAudio()) {
+            return true;
+        } else if (type == VIDEO && stream->isVideo()) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 int64_t ATSParser::Program::convertPTSToTimestamp(uint64_t PTS) {
+    PTS = recoverPTS(PTS);
+
     if (!(mParser->mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)) {
         if (!mFirstPTSValid) {
             mFirstPTSValid = true;
@@ -665,7 +747,7 @@
             int64_t resumeAtMediaTimeUs =
                 mProgram->convertPTSToTimestamp(resumeAtPTS);
 
-            extra->setInt64("resume-at-mediatimeUs", resumeAtMediaTimeUs);
+            extra->setInt64("resume-at-mediaTimeUs", resumeAtMediaTimeUs);
         }
     }
 
@@ -1084,7 +1166,8 @@
 
         if (payload_unit_start_indicator) {
             if (!section->isEmpty()) {
-                return ERROR_UNSUPPORTED;
+                ALOGW("parsePID encounters payload_unit_start_indicator when section is not empty");
+                section->clear();
             }
 
             unsigned skip = br->getBits(8);
@@ -1278,6 +1361,17 @@
     return NULL;
 }
 
+bool ATSParser::hasSource(SourceType type) const {
+    for (size_t i = 0; i < mPrograms.size(); ++i) {
+        const sp<Program> &program = mPrograms.itemAt(i);
+        if (program->hasSource(type)) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 bool ATSParser::PTSTimeDeltaEstablished() {
     if (mPrograms.isEmpty()) {
         return false;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 204934d..75d76dc 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -28,7 +28,7 @@
 
 namespace android {
 
-struct ABitReader;
+class ABitReader;
 struct ABuffer;
 struct MediaSource;
 
@@ -74,6 +74,7 @@
         NUM_SOURCE_TYPES = 2
     };
     sp<MediaSource> getSource(SourceType type);
+    bool hasSource(SourceType type) const;
 
     bool PTSTimeDeltaEstablished();
 
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index ed40bdd..79a9b04 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -48,7 +48,10 @@
 }
 
 void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
-    CHECK(mFormat == NULL);
+    if (mFormat != NULL) {
+        // Only allowed to be set once. Requires explicit clear to reset.
+        return;
+    }
 
     mIsAudio = false;
     mIsVideo = false;
@@ -91,13 +94,12 @@
     while (it != mBuffers.end()) {
         sp<ABuffer> buffer = *it;
         int32_t discontinuity;
-        if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
-            break;
-        }
-
-        sp<RefBase> object;
-        if (buffer->meta()->findObject("format", &object)) {
-            return mFormat = static_cast<MetaData*>(object.get());
+        if (!buffer->meta()->findInt32("discontinuity", &discontinuity)) {
+            sp<RefBase> object;
+            if (buffer->meta()->findObject("format", &object)) {
+                setFormat(static_cast<MetaData*>(object.get()));
+                return mFormat;
+            }
         }
 
         ++it;
@@ -131,7 +133,7 @@
 
         sp<RefBase> object;
         if ((*buffer)->meta()->findObject("format", &object)) {
-            mFormat = static_cast<MetaData*>(object.get());
+            setFormat(static_cast<MetaData*>(object.get()));
         }
 
         return OK;
@@ -166,7 +168,7 @@
 
         sp<RefBase> object;
         if (buffer->meta()->findObject("format", &object)) {
-            mFormat = static_cast<MetaData*>(object.get());
+            setFormat(static_cast<MetaData*>(object.get()));
         }
 
         int64_t timeUs;
@@ -218,12 +220,19 @@
     }
 
     if (mLatestEnqueuedMeta == NULL) {
-        mLatestEnqueuedMeta = buffer->meta();
+        mLatestEnqueuedMeta = buffer->meta()->dup();
     } else {
         int64_t latestTimeUs = 0;
+        int64_t frameDeltaUs = 0;
         CHECK(mLatestEnqueuedMeta->findInt64("timeUs", &latestTimeUs));
         if (lastQueuedTimeUs > latestTimeUs) {
-            mLatestEnqueuedMeta = buffer->meta();
+            mLatestEnqueuedMeta = buffer->meta()->dup();
+            frameDeltaUs = lastQueuedTimeUs - latestTimeUs;
+            mLatestEnqueuedMeta->setInt64("durationUs", frameDeltaUs);
+        } else if (!mLatestEnqueuedMeta->findInt64("durationUs", &frameDeltaUs)) {
+            // For B frames
+            frameDeltaUs = latestTimeUs - lastQueuedTimeUs;
+            mLatestEnqueuedMeta->setInt64("durationUs", frameDeltaUs);
         }
     }
 }
@@ -262,15 +271,15 @@
         }
     }
 
+    mEOSResult = OK;
+    mLastQueuedTimeUs = 0;
+    mLatestEnqueuedMeta = NULL;
+
     if (type == ATSParser::DISCONTINUITY_NONE) {
         return;
     }
 
-    mEOSResult = OK;
-    mLastQueuedTimeUs = 0;
-    mLatestEnqueuedMeta = NULL;
     ++mQueuedDiscontinuityCount;
-
     sp<ABuffer> buffer = new ABuffer(0);
     buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
     buffer->meta()->setMessage("extra", extra);
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 3c8f03e..88da275 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -63,8 +63,6 @@
         const uint8_t *ptr, size_t size, sp<MetaData> *metaData) {
     static const unsigned channelCountTable[] = {2, 1, 2, 3, 3, 4, 4, 5};
     static const unsigned samplingRateTable[] = {48000, 44100, 32000};
-    static const unsigned rates[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256,
-            320, 384, 448, 512, 576, 640};
 
     static const unsigned frameSizeTable[19][3] = {
         { 64, 69, 96 },
@@ -89,7 +87,6 @@
     };
 
     ABitReader bits(ptr, size);
-    unsigned syncStartPos = 0;  // in bytes
     if (bits.numBitsLeft() < 16) {
         return 0;
     }
@@ -121,11 +118,11 @@
         return 0;
     }
 
-    unsigned bsmod = bits.getBits(3);
+    unsigned bsmod __unused = bits.getBits(3);
     unsigned acmod = bits.getBits(3);
-    unsigned cmixlev = 0;
-    unsigned surmixlev = 0;
-    unsigned dsurmod = 0;
+    unsigned cmixlev __unused = 0;
+    unsigned surmixlev __unused = 0;
+    unsigned dsurmod __unused = 0;
 
     if ((acmod & 1) > 0 && acmod != 1) {
         if (bits.numBitsLeft() < 2) {
@@ -173,8 +170,9 @@
     return parseAC3SyncFrame(ptr, size, NULL) > 0;
 }
 
-static bool IsSeeminglyValidADTSHeader(const uint8_t *ptr, size_t size) {
-    if (size < 3) {
+static bool IsSeeminglyValidADTSHeader(
+        const uint8_t *ptr, size_t size, size_t *frameLength) {
+    if (size < 7) {
         // Not enough data to verify header.
         return false;
     }
@@ -197,6 +195,13 @@
         return false;
     }
 
+    size_t frameLengthInHeader =
+            ((ptr[3] & 3) << 11) + (ptr[4] << 3) + ((ptr[5] >> 5) & 7);
+    if (frameLengthInHeader > size) {
+        return false;
+    }
+
+    *frameLength = frameLengthInHeader;
     return true;
 }
 
@@ -318,8 +323,10 @@
                 }
 #else
                 ssize_t startOffset = -1;
+                size_t frameLength;
                 for (size_t i = 0; i < size; ++i) {
-                    if (IsSeeminglyValidADTSHeader(&ptr[i], size - i)) {
+                    if (IsSeeminglyValidADTSHeader(
+                            &ptr[i], size - i, &frameLength)) {
                         startOffset = i;
                         break;
                     }
@@ -335,6 +342,12 @@
                           startOffset);
                 }
 
+                if (frameLength != size - startOffset) {
+                    ALOGV("First ADTS AAC frame length is %zd bytes, "
+                          "while the buffer size is %zd bytes.",
+                          frameLength, size - startOffset);
+                }
+
                 data = &ptr[startOffset];
                 size -= startOffset;
 #endif
@@ -540,7 +553,7 @@
     CHECK_EQ(bits.getBits(8), 0xa0);
     unsigned numAUs = bits.getBits(8);
     bits.skipBits(8);
-    unsigned quantization_word_length = bits.getBits(2);
+    unsigned quantization_word_length __unused = bits.getBits(2);
     unsigned audio_sampling_frequency = bits.getBits(3);
     unsigned num_channels = bits.getBits(3);
 
@@ -616,7 +629,7 @@
 
         CHECK_EQ(bits.getBits(12), 0xfffu);
         bits.skipBits(3);  // ID, layer
-        bool protection_absent = bits.getBits(1) != 0;
+        bool protection_absent __unused = bits.getBits(1) != 0;
 
         if (mFormat == NULL) {
             unsigned profile = bits.getBits(2);
@@ -665,7 +678,7 @@
             return NULL;
         }
 
-        size_t headerSize = protection_absent ? 7 : 9;
+        size_t headerSize __unused = protection_absent ? 7 : 9;
 
         offset += aac_frame_length;
     }
@@ -717,11 +730,6 @@
     return timeUs;
 }
 
-struct NALPosition {
-    size_t nalOffset;
-    size_t nalSize;
-};
-
 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
     const uint8_t *data = mBuffer->data();
 
@@ -729,6 +737,7 @@
     Vector<NALPosition> nals;
 
     size_t totalSize = 0;
+    size_t seiCount = 0;
 
     status_t err;
     const uint8_t *nalStart;
@@ -758,6 +767,9 @@
             // next frame.
 
             flush = true;
+        } else if (nalType == 6 && nalSize > 0) {
+            // found non-zero sized SEI
+            ++seiCount;
         }
 
         if (flush) {
@@ -766,21 +778,29 @@
 
             size_t auSize = 4 * nals.size() + totalSize;
             sp<ABuffer> accessUnit = new ABuffer(auSize);
+            sp<ABuffer> sei;
+
+            if (seiCount > 0) {
+                sei = new ABuffer(seiCount * sizeof(NALPosition));
+                accessUnit->meta()->setBuffer("sei", sei);
+            }
 
 #if !LOG_NDEBUG
             AString out;
 #endif
 
             size_t dstOffset = 0;
+            size_t seiIndex = 0;
             for (size_t i = 0; i < nals.size(); ++i) {
                 const NALPosition &pos = nals.itemAt(i);
 
                 unsigned nalType = mBuffer->data()[pos.nalOffset] & 0x1f;
 
-                if (nalType == 6) {
-                    sp<ABuffer> sei = new ABuffer(pos.nalSize);
-                    memcpy(sei->data(), mBuffer->data() + pos.nalOffset, pos.nalSize);
-                    accessUnit->meta()->setBuffer("sei", sei);
+                if (nalType == 6 && pos.nalSize > 0) {
+                    CHECK_LT(seiIndex, sei->size() / sizeof(NALPosition));
+                    NALPosition &seiPos = ((NALPosition *)sei->data())[seiIndex++];
+                    seiPos.nalOffset = dstOffset + 4;
+                    seiPos.nalSize = pos.nalSize;
                 }
 
 #if !LOG_NDEBUG
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h
index a2cca77..45b4624 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.h
+++ b/media/libstagefright/mpeg2ts/ESQueue.h
@@ -26,7 +26,7 @@
 namespace android {
 
 struct ABuffer;
-struct MetaData;
+class MetaData;
 
 struct ElementaryStreamQueue {
     enum Mode {
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index 35ca118..1f43d6d 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -159,7 +159,6 @@
     int numPacketsParsed = 0;
 
     while (feedMore() == OK) {
-        ATSParser::SourceType type;
         if (haveAudio && haveVideo) {
             break;
         }
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index aaa8334..07ea605 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -1,11 +1,8 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-ifeq ($(TARGET_DEVICE), manta)
-    LOCAL_CFLAGS += -DSURFACE_IS_BGR32
-endif
-
 LOCAL_SRC_FILES:=                     \
+        FrameDropper.cpp              \
         GraphicBufferSource.cpp       \
         OMX.cpp                       \
         OMXMaster.cpp                 \
diff --git a/media/libstagefright/omx/FrameDropper.cpp b/media/libstagefright/omx/FrameDropper.cpp
new file mode 100644
index 0000000..9fba0b7
--- /dev/null
+++ b/media/libstagefright/omx/FrameDropper.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "FrameDropper"
+#include <utils/Log.h>
+
+#include "FrameDropper.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+static const int64_t kMaxJitterUs = 2000;
+
+FrameDropper::FrameDropper()
+    : mDesiredMinTimeUs(-1),
+      mMinIntervalUs(0) {
+}
+
+FrameDropper::~FrameDropper() {
+}
+
+status_t FrameDropper::setMaxFrameRate(float maxFrameRate) {
+    if (maxFrameRate <= 0) {
+        ALOGE("framerate should be positive but got %f.", maxFrameRate);
+        return BAD_VALUE;
+    }
+    mMinIntervalUs = (int64_t) (1000000.0f / maxFrameRate);
+    return OK;
+}
+
+bool FrameDropper::shouldDrop(int64_t timeUs) {
+    if (mMinIntervalUs <= 0) {
+        return false;
+    }
+
+    if (mDesiredMinTimeUs < 0) {
+        mDesiredMinTimeUs = timeUs + mMinIntervalUs;
+        ALOGV("first frame %lld, next desired frame %lld", timeUs, mDesiredMinTimeUs);
+        return false;
+    }
+
+    if (timeUs < (mDesiredMinTimeUs - kMaxJitterUs)) {
+        ALOGV("drop frame %lld, desired frame %lld, diff %lld",
+                timeUs, mDesiredMinTimeUs, mDesiredMinTimeUs - timeUs);
+        return true;
+    }
+
+    int64_t n = (timeUs - mDesiredMinTimeUs + kMaxJitterUs) / mMinIntervalUs;
+    mDesiredMinTimeUs += (n + 1) * mMinIntervalUs;
+    ALOGV("keep frame %lld, next desired frame %lld, diff %lld",
+            timeUs, mDesiredMinTimeUs, mDesiredMinTimeUs - timeUs);
+    return false;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/omx/FrameDropper.h b/media/libstagefright/omx/FrameDropper.h
new file mode 100644
index 0000000..c5a6d4b
--- /dev/null
+++ b/media/libstagefright/omx/FrameDropper.h
@@ -0,0 +1,50 @@
+/*
+ * 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 FRAME_DROPPER_H_
+
+#define FRAME_DROPPER_H_
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+struct FrameDropper : public RefBase {
+    // No frames will be dropped until a valid max frame rate is set.
+    FrameDropper();
+
+    // maxFrameRate required to be positive.
+    status_t setMaxFrameRate(float maxFrameRate);
+
+    // Returns false if max frame rate has not been set via setMaxFrameRate.
+    bool shouldDrop(int64_t timeUs);
+
+protected:
+    virtual ~FrameDropper();
+
+private:
+    int64_t mDesiredMinTimeUs;
+    int64_t mMinIntervalUs;
+
+    DISALLOW_EVIL_CONSTRUCTORS(FrameDropper);
+};
+
+}  // namespace android
+
+#endif  // FRAME_DROPPER_H_
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 3e70956..477cfc6 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -28,8 +28,10 @@
 
 #include <media/hardware/MetadataBufferType.h>
 #include <ui/GraphicBuffer.h>
+#include <gui/BufferItem.h>
 
 #include <inttypes.h>
+#include "FrameDropper.h"
 
 namespace android {
 
@@ -53,9 +55,9 @@
     mRepeatAfterUs(-1ll),
     mRepeatLastFrameGeneration(0),
     mRepeatLastFrameTimestamp(-1ll),
-    mLatestSubmittedBufferId(-1),
-    mLatestSubmittedBufferFrameNum(0),
-    mLatestSubmittedBufferUseCount(0),
+    mLatestBufferId(-1),
+    mLatestBufferFrameNum(0),
+    mLatestBufferUseCount(0),
     mRepeatBufferDeferred(false),
     mTimePerCaptureUs(-1ll),
     mTimePerFrameUs(-1ll),
@@ -152,9 +154,9 @@
         mLooper->registerHandler(mReflector);
         mLooper->start();
 
-        if (mLatestSubmittedBufferId >= 0) {
+        if (mLatestBufferId >= 0) {
             sp<AMessage> msg =
-                new AMessage(kWhatRepeatLastFrame, mReflector->id());
+                new AMessage(kWhatRepeatLastFrame, mReflector);
 
             msg->setInt32("generation", ++mRepeatLastFrameGeneration);
             msg->post(mRepeatAfterUs);
@@ -287,8 +289,8 @@
         ALOGV("cbi %d matches bq slot %d, handle=%p",
                 cbi, id, mBufferSlot[id]->handle);
 
-        if (id == mLatestSubmittedBufferId) {
-            CHECK_GT(mLatestSubmittedBufferUseCount--, 0);
+        if (id == mLatestBufferId) {
+            CHECK_GT(mLatestBufferUseCount--, 0);
         } else {
             mConsumer->releaseBuffer(id, codecBuffer.mFrameNumber,
                     EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
@@ -313,11 +315,11 @@
         ALOGV("buffer freed, EOS pending");
         submitEndOfInputStream_l();
     } else if (mRepeatBufferDeferred) {
-        bool success = repeatLatestSubmittedBuffer_l();
+        bool success = repeatLatestBuffer_l();
         if (success) {
-            ALOGV("deferred repeatLatestSubmittedBuffer_l SUCCESS");
+            ALOGV("deferred repeatLatestBuffer_l SUCCESS");
         } else {
-            ALOGV("deferred repeatLatestSubmittedBuffer_l FAILURE");
+            ALOGV("deferred repeatLatestBuffer_l FAILURE");
         }
         mRepeatBufferDeferred = false;
     }
@@ -359,7 +361,7 @@
         mSuspended = true;
 
         while (mNumFramesAvailable > 0) {
-            BufferQueue::BufferItem item;
+            BufferItem item;
             status_t err = mConsumer->acquireBuffer(&item, 0);
 
             if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
@@ -382,12 +384,12 @@
     mSuspended = false;
 
     if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) {
-        if (repeatLatestSubmittedBuffer_l()) {
-            ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l SUCCESS");
+        if (repeatLatestBuffer_l()) {
+            ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
 
             mRepeatBufferDeferred = false;
         } else {
-            ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l FAILURE");
+            ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
         }
     }
 }
@@ -409,7 +411,7 @@
 
     ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu",
             mNumFramesAvailable);
-    BufferQueue::BufferItem item;
+    BufferItem item;
     status_t err = mConsumer->acquireBuffer(&item, 0);
     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
         // shouldn't happen
@@ -441,12 +443,22 @@
 
     // only submit sample if start time is unspecified, or sample
     // is queued after the specified start time
+    bool dropped = false;
     if (mSkipFramesBeforeNs < 0ll || item.mTimestamp >= mSkipFramesBeforeNs) {
         // if start time is set, offset time stamp by start time
         if (mSkipFramesBeforeNs > 0) {
             item.mTimestamp -= mSkipFramesBeforeNs;
         }
-        err = submitBuffer_l(item, cbi);
+
+        int64_t timeUs = item.mTimestamp / 1000;
+        if (mFrameDropper != NULL && mFrameDropper->shouldDrop(timeUs)) {
+            ALOGV("skipping frame (%lld) to meet max framerate", static_cast<long long>(timeUs));
+            // set err to OK so that the skipped frame can still be saved as the lastest frame
+            err = OK;
+            dropped = true;
+        } else {
+            err = submitBuffer_l(item, cbi);
+        }
     }
 
     if (err != OK) {
@@ -455,46 +467,46 @@
                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
     } else {
         ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi);
-        setLatestSubmittedBuffer_l(item);
+        setLatestBuffer_l(item, dropped);
     }
 
     return true;
 }
 
-bool GraphicBufferSource::repeatLatestSubmittedBuffer_l() {
+bool GraphicBufferSource::repeatLatestBuffer_l() {
     CHECK(mExecuting && mNumFramesAvailable == 0);
 
-    if (mLatestSubmittedBufferId < 0 || mSuspended) {
+    if (mLatestBufferId < 0 || mSuspended) {
         return false;
     }
-    if (mBufferSlot[mLatestSubmittedBufferId] == NULL) {
+    if (mBufferSlot[mLatestBufferId] == NULL) {
         // This can happen if the remote side disconnects, causing
         // onBuffersReleased() to NULL out our copy of the slots.  The
         // buffer is gone, so we have nothing to show.
         //
         // To be on the safe side we try to release the buffer.
-        ALOGD("repeatLatestSubmittedBuffer_l: slot was NULL");
+        ALOGD("repeatLatestBuffer_l: slot was NULL");
         mConsumer->releaseBuffer(
-                mLatestSubmittedBufferId,
-                mLatestSubmittedBufferFrameNum,
+                mLatestBufferId,
+                mLatestBufferFrameNum,
                 EGL_NO_DISPLAY,
                 EGL_NO_SYNC_KHR,
                 Fence::NO_FENCE);
-        mLatestSubmittedBufferId = -1;
-        mLatestSubmittedBufferFrameNum = 0;
+        mLatestBufferId = -1;
+        mLatestBufferFrameNum = 0;
         return false;
     }
 
     int cbi = findAvailableCodecBuffer_l();
     if (cbi < 0) {
         // No buffers available, bail.
-        ALOGV("repeatLatestSubmittedBuffer_l: no codec buffers.");
+        ALOGV("repeatLatestBuffer_l: no codec buffers.");
         return false;
     }
 
-    BufferQueue::BufferItem item;
-    item.mBuf = mLatestSubmittedBufferId;
-    item.mFrameNumber = mLatestSubmittedBufferFrameNum;
+    BufferItem item;
+    item.mBuf = mLatestBufferId;
+    item.mFrameNumber = mLatestBufferFrameNum;
     item.mTimestamp = mRepeatLastFrameTimestamp;
 
     status_t err = submitBuffer_l(item, cbi);
@@ -503,7 +515,7 @@
         return false;
     }
 
-    ++mLatestSubmittedBufferUseCount;
+    ++mLatestBufferUseCount;
 
     /* repeat last frame up to kRepeatLastFrameCount times.
      * in case of static scene, a single repeat might not get rid of encoder
@@ -513,7 +525,7 @@
         mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
 
         if (mReflector != NULL) {
-            sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id());
+            sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
             msg->setInt32("generation", ++mRepeatLastFrameGeneration);
             msg->post(mRepeatAfterUs);
         }
@@ -522,31 +534,31 @@
     return true;
 }
 
-void GraphicBufferSource::setLatestSubmittedBuffer_l(
-        const BufferQueue::BufferItem &item) {
-    ALOGV("setLatestSubmittedBuffer_l");
+void GraphicBufferSource::setLatestBuffer_l(
+        const BufferItem &item, bool dropped) {
+    ALOGV("setLatestBuffer_l");
 
-    if (mLatestSubmittedBufferId >= 0) {
-        if (mLatestSubmittedBufferUseCount == 0) {
+    if (mLatestBufferId >= 0) {
+        if (mLatestBufferUseCount == 0) {
             mConsumer->releaseBuffer(
-                    mLatestSubmittedBufferId,
-                    mLatestSubmittedBufferFrameNum,
+                    mLatestBufferId,
+                    mLatestBufferFrameNum,
                     EGL_NO_DISPLAY,
                     EGL_NO_SYNC_KHR,
                     Fence::NO_FENCE);
         }
     }
 
-    mLatestSubmittedBufferId = item.mBuf;
-    mLatestSubmittedBufferFrameNum = item.mFrameNumber;
+    mLatestBufferId = item.mBuf;
+    mLatestBufferFrameNum = item.mFrameNumber;
     mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
 
-    mLatestSubmittedBufferUseCount = 1;
+    mLatestBufferUseCount = dropped ? 0 : 1;
     mRepeatBufferDeferred = false;
     mRepeatLastFrameCount = kRepeatLastFrameCount;
 
     if (mReflector != NULL) {
-        sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id());
+        sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
         msg->setInt32("generation", ++mRepeatLastFrameGeneration);
         msg->post(mRepeatAfterUs);
     }
@@ -579,7 +591,7 @@
     return OK;
 }
 
-int64_t GraphicBufferSource::getTimestamp(const BufferQueue::BufferItem &item) {
+int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) {
     int64_t timeUs = item.mTimestamp / 1000;
 
     if (mTimePerCaptureUs > 0ll) {
@@ -640,7 +652,7 @@
 }
 
 status_t GraphicBufferSource::submitBuffer_l(
-        const BufferQueue::BufferItem &item, int cbi) {
+        const BufferItem &item, int cbi) {
     ALOGV("submitBuffer_l cbi=%d", cbi);
 
     int64_t timeUs = getTimestamp(item);
@@ -750,7 +762,7 @@
 }
 
 // BufferQueue::ConsumerListener callback
-void GraphicBufferSource::onFrameAvailable() {
+void GraphicBufferSource::onFrameAvailable(const BufferItem& /*item*/) {
     Mutex::Autolock autoLock(mMutex);
 
     ALOGV("onFrameAvailable exec=%d avail=%zu",
@@ -766,7 +778,7 @@
             ALOGV("onFrameAvailable: suspended, ignoring frame");
         }
 
-        BufferQueue::BufferItem item;
+        BufferItem item;
         status_t err = mConsumer->acquireBuffer(&item, 0);
         if (err == OK) {
             // If this is the first time we're seeing this buffer, add it to our
@@ -841,6 +853,23 @@
     return OK;
 }
 
+status_t GraphicBufferSource::setMaxFps(float maxFps) {
+    Mutex::Autolock autoLock(mMutex);
+
+    if (mExecuting) {
+        return INVALID_OPERATION;
+    }
+
+    mFrameDropper = new FrameDropper();
+    status_t err = mFrameDropper->setMaxFrameRate(maxFps);
+    if (err != OK) {
+        mFrameDropper.clear();
+        return err;
+    }
+
+    return OK;
+}
+
 void GraphicBufferSource::setSkipFramesBeforeUs(int64_t skipFramesBeforeUs) {
     Mutex::Autolock autoLock(mMutex);
 
@@ -879,12 +908,12 @@
                 break;
             }
 
-            bool success = repeatLatestSubmittedBuffer_l();
+            bool success = repeatLatestBuffer_l();
 
             if (success) {
-                ALOGV("repeatLatestSubmittedBuffer_l SUCCESS");
+                ALOGV("repeatLatestBuffer_l SUCCESS");
             } else {
-                ALOGV("repeatLatestSubmittedBuffer_l FAILURE");
+                ALOGV("repeatLatestBuffer_l FAILURE");
                 mRepeatBufferDeferred = true;
             }
             break;
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index c0860ab..1067472 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -30,6 +30,8 @@
 
 namespace android {
 
+class FrameDropper;
+
 /*
  * This class is used to feed OMX codecs from a Surface via BufferQueue.
  *
@@ -119,6 +121,9 @@
     // of suspension on input.
     status_t setMaxTimestampGapUs(int64_t maxGapUs);
 
+    // When set, the max frame rate fed to the encoder will be capped at maxFps.
+    status_t setMaxFps(float maxFps);
+
     // Sets the time lapse (or slow motion) parameters.
     // data[0] is the time (us) between two frames for playback
     // data[1] is the time (us) between two frames for capture
@@ -137,7 +142,7 @@
     // into the codec buffer, and call Empty[This]Buffer.  If we're not yet
     // executing or there's no codec buffer available, we just increment
     // mNumFramesAvailable and return.
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
 
     // BufferQueue::ConsumerListener interface, called when the client has
     // released one or more GraphicBuffers.  We clear out the appropriate
@@ -187,15 +192,15 @@
 
     // Marks the mCodecBuffers entry as in-use, copies the GraphicBuffer
     // reference into the codec buffer, and submits the data to the codec.
-    status_t submitBuffer_l(const BufferQueue::BufferItem &item, int cbi);
+    status_t submitBuffer_l(const BufferItem &item, int cbi);
 
     // Submits an empty buffer, with the EOS flag set.   Returns without
     // doing anything if we don't have a codec buffer available.
     void submitEndOfInputStream_l();
 
-    void setLatestSubmittedBuffer_l(const BufferQueue::BufferItem &item);
-    bool repeatLatestSubmittedBuffer_l();
-    int64_t getTimestamp(const BufferQueue::BufferItem &item);
+    void setLatestBuffer_l(const BufferItem &item, bool dropped);
+    bool repeatLatestBuffer_l();
+    int64_t getTimestamp(const BufferItem &item);
 
     // Lock, covers all member variables.
     mutable Mutex mMutex;
@@ -250,6 +255,8 @@
     int64_t mPrevModifiedTimeUs;
     int64_t mSkipFramesBeforeNs;
 
+    sp<FrameDropper> mFrameDropper;
+
     sp<ALooper> mLooper;
     sp<AHandlerReflector<GraphicBufferSource> > mReflector;
 
@@ -258,11 +265,11 @@
     int64_t mRepeatLastFrameTimestamp;
     int32_t mRepeatLastFrameCount;
 
-    int mLatestSubmittedBufferId;
-    uint64_t mLatestSubmittedBufferFrameNum;
-    int32_t mLatestSubmittedBufferUseCount;
+    int mLatestBufferId;
+    uint64_t mLatestBufferFrameNum;
+    int32_t mLatestBufferUseCount;
 
-    // The previously submitted buffer should've been repeated but
+    // The previous buffer should've been repeated but
     // no codec buffer was available at the time.
     bool mRepeatBufferDeferred;
 
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 41407e4..f8d38ff 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -225,7 +225,7 @@
 
     *node = 0;
 
-    OMXNodeInstance *instance = new OMXNodeInstance(this, observer);
+    OMXNodeInstance *instance = new OMXNodeInstance(this, observer, name);
 
     OMX_COMPONENTTYPE *handle;
     OMX_ERRORTYPE err = mMaster->makeComponentInstance(
@@ -245,8 +245,8 @@
 
     instance->setHandle(*node, handle);
 
-    mLiveNodes.add(observer->asBinder(), instance);
-    observer->asBinder()->linkToDeath(this);
+    mLiveNodes.add(IInterface::asBinder(observer), instance);
+    IInterface::asBinder(observer)->linkToDeath(this);
 
     return OK;
 }
@@ -256,7 +256,7 @@
 
     {
         Mutex::Autolock autoLock(mLock);
-        ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
+        ssize_t index = mLiveNodes.indexOfKey(IInterface::asBinder(instance->observer()));
         if (index < 0) {
             // This could conceivably happen if the observer dies at roughly the
             // same time that a client attempts to free the node explicitly.
@@ -265,7 +265,7 @@
         mLiveNodes.removeItemsAt(index);
     }
 
-    instance->observer()->asBinder()->unlinkToDeath(this);
+    IInterface::asBinder(instance->observer())->unlinkToDeath(this);
 
     status_t err = instance->freeNode(mMaster);
 
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index f9c84e2..4779d6a 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -18,11 +18,15 @@
 #define LOG_TAG "OMXNodeInstance"
 #include <utils/Log.h>
 
+#include <inttypes.h>
+
 #include "../include/OMXNodeInstance.h"
 #include "OMXMaster.h"
 #include "GraphicBufferSource.h"
 
 #include <OMX_Component.h>
+#include <OMX_IndexExt.h>
+#include <OMX_AsString.h>
 
 #include <binder/IMemory.h>
 #include <gui/BufferQueue.h>
@@ -30,7 +34,68 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaErrors.h>
 
+#include <utils/misc.h>
+
 static const OMX_U32 kPortIndexInput = 0;
+static const OMX_U32 kPortIndexOutput = 1;
+
+#define CLOGW(fmt, ...) ALOGW("[%x:%s] " fmt, mNodeID, mName, ##__VA_ARGS__)
+
+#define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \
+    ALOGE_IF(cond, #fn "(%x:%s, " fmt ") ERROR: %s(%#x)", \
+    mNodeID, mName, ##__VA_ARGS__, asString(err), err)
+#define CLOG_ERROR(fn, err, fmt, ...) CLOG_ERROR_IF(true, fn, err, fmt, ##__VA_ARGS__)
+#define CLOG_IF_ERROR(fn, err, fmt, ...) \
+    CLOG_ERROR_IF((err) != OMX_ErrorNone, fn, err, fmt, ##__VA_ARGS__)
+
+#define CLOGI_(level, fn, fmt, ...) \
+    ALOGI_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__)
+#define CLOGD_(level, fn, fmt, ...) \
+    ALOGD_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__)
+
+#define CLOG_LIFE(fn, fmt, ...)     CLOGI_(ADebug::kDebugLifeCycle,     fn, fmt, ##__VA_ARGS__)
+#define CLOG_STATE(fn, fmt, ...)    CLOGI_(ADebug::kDebugState,         fn, fmt, ##__VA_ARGS__)
+#define CLOG_CONFIG(fn, fmt, ...)   CLOGI_(ADebug::kDebugConfig,        fn, fmt, ##__VA_ARGS__)
+#define CLOG_INTERNAL(fn, fmt, ...) CLOGD_(ADebug::kDebugInternalState, fn, fmt, ##__VA_ARGS__)
+
+#define CLOG_DEBUG_IF(cond, fn, fmt, ...) \
+    ALOGD_IF(cond, #fn "(%x, " fmt ")", mNodeID, ##__VA_ARGS__)
+
+#define CLOG_BUFFER(fn, fmt, ...) \
+    CLOG_DEBUG_IF(DEBUG >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
+#define CLOG_BUMPED_BUFFER(fn, fmt, ...) \
+    CLOG_DEBUG_IF(DEBUG_BUMP >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
+
+/* buffer formatting */
+#define BUFFER_FMT(port, fmt, ...) "%s:%u " fmt, portString(port), (port), ##__VA_ARGS__
+#define NEW_BUFFER_FMT(buffer_id, port, fmt, ...) \
+    BUFFER_FMT(port, fmt ") (#%zu => %#x", ##__VA_ARGS__, mActiveBuffers.size(), (buffer_id))
+
+#define SIMPLE_BUFFER(port, size, data) BUFFER_FMT(port, "%zu@%p", (size), (data))
+#define SIMPLE_NEW_BUFFER(buffer_id, port, size, data) \
+    NEW_BUFFER_FMT(buffer_id, port, "%zu@%p", (size), (data))
+
+#define EMPTY_BUFFER(addr, header) "%#x [%u@%p]", \
+    (addr), (header)->nAllocLen, (header)->pBuffer
+#define FULL_BUFFER(addr, header) "%#" PRIxPTR " [%u@%p (%u..+%u) f=%x ts=%lld]", \
+    (intptr_t)(addr), (header)->nAllocLen, (header)->pBuffer, \
+    (header)->nOffset, (header)->nFilledLen, (header)->nFlags, (header)->nTimeStamp
+
+#define WITH_STATS_WRAPPER(fmt, ...) fmt " { IN=%zu/%zu OUT=%zu/%zu }", ##__VA_ARGS__, \
+    mInputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexInput], \
+    mOutputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexOutput]
+// TRICKY: this is needed so formatting macros expand before substitution
+#define WITH_STATS(fmt, ...) WITH_STATS_WRAPPER(fmt, ##__VA_ARGS__)
+
+template<class T>
+static void InitOMXParams(T *params) {
+    memset(params, 0, sizeof(T));
+    params->nSize = sizeof(T);
+    params->nVersion.s.nVersionMajor = 1;
+    params->nVersion.s.nVersionMinor = 0;
+    params->nVersion.s.nRevision = 0;
+    params->nVersion.s.nStep = 0;
+}
 
 namespace android {
 
@@ -56,8 +121,8 @@
         }
 
         memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
-               header->pBuffer + header->nOffset,
-               header->nFilledLen);
+                header->pBuffer + header->nOffset,
+                header->nFilledLen);
     }
 
     void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
@@ -66,8 +131,8 @@
         }
 
         memcpy(header->pBuffer + header->nOffset,
-               (const OMX_U8 *)mMem->pointer() + header->nOffset,
-               header->nFilledLen);
+                (const OMX_U8 *)mMem->pointer() + header->nOffset,
+                header->nFilledLen);
     }
 
     void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) {
@@ -89,8 +154,17 @@
     &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
 };
 
+static inline const char *portString(OMX_U32 portIndex) {
+    switch (portIndex) {
+        case kPortIndexInput:  return "Input";
+        case kPortIndexOutput: return "Output";
+        case ~0U:              return "All";
+        default:               return "port";
+    }
+}
+
 OMXNodeInstance::OMXNodeInstance(
-        OMX *owner, const sp<IOMXObserver> &observer)
+        OMX *owner, const sp<IOMXObserver> &observer, const char *name)
     : mOwner(owner),
       mNodeID(0),
       mHandle(NULL),
@@ -100,15 +174,25 @@
       , mBufferIDCount(0)
 #endif
 {
+    mName = ADebug::GetDebugName(name);
+    DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug");
+    ALOGV("debug level for %s is %d", name, DEBUG);
+    DEBUG_BUMP = DEBUG;
+    mNumPortBuffers[0] = 0;
+    mNumPortBuffers[1] = 0;
+    mDebugLevelBumpPendingBuffers[0] = 0;
+    mDebugLevelBumpPendingBuffers[1] = 0;
 }
 
 OMXNodeInstance::~OMXNodeInstance() {
+    free(mName);
     CHECK(mHandle == NULL);
 }
 
 void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
-    CHECK(mHandle == NULL);
     mNodeID = node_id;
+    CLOG_LIFE(allocateNode, "handle=%p", handle);
+    CHECK(mHandle == NULL);
     mHandle = handle;
 }
 
@@ -120,6 +204,7 @@
 void OMXNodeInstance::setGraphicBufferSource(
         const sp<GraphicBufferSource>& bufferSource) {
     Mutex::Autolock autoLock(mGraphicBufferSourceLock);
+    CLOG_INTERNAL(setGraphicBufferSource, "%p", bufferSource.get());
     mGraphicBufferSource = bufferSource;
 }
 
@@ -140,6 +225,7 @@
         case OMX_ErrorNone:
             return OK;
         case OMX_ErrorUnsupportedSetting:
+        case OMX_ErrorUnsupportedIndex:
             return ERROR_UNSUPPORTED;
         default:
             return UNKNOWN_ERROR;
@@ -147,6 +233,7 @@
 }
 
 status_t OMXNodeInstance::freeNode(OMXMaster *master) {
+    CLOG_LIFE(freeNode, "handle=%p", mHandle);
     static int32_t kMaxNumIterations = 10;
 
     // exit if we have already freed the node
@@ -175,10 +262,11 @@
             OMX_ERRORTYPE err;
             int32_t iteration = 0;
             while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
-                   && state != OMX_StateIdle
-                   && state != OMX_StateInvalid) {
+                    && state != OMX_StateIdle
+                    && state != OMX_StateInvalid) {
                 if (++iteration > kMaxNumIterations) {
-                    ALOGE("component failed to enter Idle state, aborting.");
+                    CLOGW("failed to enter Idle state (now %s(%d), aborting.",
+                            asString(state), state);
                     state = OMX_StateInvalid;
                     break;
                 }
@@ -204,10 +292,11 @@
             OMX_ERRORTYPE err;
             int32_t iteration = 0;
             while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
-                   && state != OMX_StateLoaded
-                   && state != OMX_StateInvalid) {
+                    && state != OMX_StateLoaded
+                    && state != OMX_StateInvalid) {
                 if (++iteration > kMaxNumIterations) {
-                    ALOGE("component failed to enter Loaded state, aborting.");
+                    CLOGW("failed to enter Loaded state (now %s(%d), aborting.",
+                            asString(state), state);
                     state = OMX_StateInvalid;
                     break;
                 }
@@ -225,20 +314,18 @@
             break;
 
         default:
-            CHECK(!"should not be here, unknown state.");
+            LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state);
             break;
     }
 
-    ALOGV("calling destroyComponentInstance");
+    ALOGV("[%x:%s] calling destroyComponentInstance", mNodeID, mName);
     OMX_ERRORTYPE err = master->destroyComponentInstance(
             static_cast<OMX_COMPONENTTYPE *>(mHandle));
-    ALOGV("destroyComponentInstance returned err %d", err);
 
     mHandle = NULL;
-
-    if (err != OMX_ErrorNone) {
-        ALOGE("FreeHandle FAILED with error 0x%08x.", err);
-    }
+    CLOG_IF_ERROR(freeNode, err, "");
+    free(mName);
+    mName = NULL;
 
     mOwner->invalidateNodeID(mNodeID);
     mNodeID = 0;
@@ -270,7 +357,17 @@
 
     Mutex::Autolock autoLock(mLock);
 
+    // bump internal-state debug level for 2 input and output frames past a command
+    {
+        Mutex::Autolock _l(mDebugLock);
+        bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */);
+    }
+
+    const char *paramString =
+        cmd == OMX_CommandStateSet ? asString((OMX_STATETYPE)param) : portString(param);
+    CLOG_STATE(sendCommand, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param);
     OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
+    CLOG_IF_ERROR(sendCommand, err, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param);
     return StatusFromOMXError(err);
 }
 
@@ -279,17 +376,23 @@
     Mutex::Autolock autoLock(mLock);
 
     OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
-    ALOGE_IF(err != OMX_ErrorNone, "getParameter(%d) ERROR: %#x", index, err);
+    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
+    // some errors are expected for getParameter
+    if (err != OMX_ErrorNoMore) {
+        CLOG_IF_ERROR(getParameter, err, "%s(%#x)", asString(extIndex), index);
+    }
     return StatusFromOMXError(err);
 }
 
 status_t OMXNodeInstance::setParameter(
-        OMX_INDEXTYPE index, const void *params, size_t /* size */) {
+        OMX_INDEXTYPE index, const void *params, size_t size) {
     Mutex::Autolock autoLock(mLock);
+    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
+    CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
 
     OMX_ERRORTYPE err = OMX_SetParameter(
             mHandle, index, const_cast<void *>(params));
-    ALOGE_IF(err != OMX_ErrorNone, "setParameter(%d) ERROR: %#x", index, err);
+    CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index);
     return StatusFromOMXError(err);
 }
 
@@ -298,16 +401,23 @@
     Mutex::Autolock autoLock(mLock);
 
     OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
+    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
+    // some errors are expected for getConfig
+    if (err != OMX_ErrorNoMore) {
+        CLOG_IF_ERROR(getConfig, err, "%s(%#x)", asString(extIndex), index);
+    }
     return StatusFromOMXError(err);
 }
 
 status_t OMXNodeInstance::setConfig(
-        OMX_INDEXTYPE index, const void *params, size_t /* size */) {
+        OMX_INDEXTYPE index, const void *params, size_t size) {
     Mutex::Autolock autoLock(mLock);
+    OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
+    CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
 
     OMX_ERRORTYPE err = OMX_SetConfig(
             mHandle, index, const_cast<void *>(params));
-
+    CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index);
     return StatusFromOMXError(err);
 }
 
@@ -315,13 +425,14 @@
     Mutex::Autolock autoLock(mLock);
 
     OMX_ERRORTYPE err = OMX_GetState(mHandle, state);
-
+    CLOG_IF_ERROR(getState, err, "");
     return StatusFromOMXError(err);
 }
 
 status_t OMXNodeInstance::enableGraphicBuffers(
         OMX_U32 portIndex, OMX_BOOL enable) {
     Mutex::Autolock autoLock(mLock);
+    CLOG_CONFIG(enableGraphicBuffers, "%s:%u, %d", portString(portIndex), portIndex, enable);
     OMX_STRING name = const_cast<OMX_STRING>(
             "OMX.google.android.index.enableAndroidNativeBuffers");
 
@@ -329,32 +440,19 @@
     OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
 
     if (err != OMX_ErrorNone) {
-        if (enable) {
-            ALOGE("OMX_GetExtensionIndex %s failed", name);
-        }
-
+        CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
         return StatusFromOMXError(err);
     }
 
-    OMX_VERSIONTYPE ver;
-    ver.s.nVersionMajor = 1;
-    ver.s.nVersionMinor = 0;
-    ver.s.nRevision = 0;
-    ver.s.nStep = 0;
-    EnableAndroidNativeBuffersParams params = {
-        sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable,
-    };
+    EnableAndroidNativeBuffersParams params;
+    InitOMXParams(&params);
+    params.nPortIndex = portIndex;
+    params.enable = enable;
 
     err = OMX_SetParameter(mHandle, index, &params);
-
-    if (err != OMX_ErrorNone) {
-        ALOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)",
-                err, err);
-
-        return UNKNOWN_ERROR;
-    }
-
-    return OK;
+    CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,
+            portString(portIndex), portIndex, enable);
+    return StatusFromOMXError(err);
 }
 
 status_t OMXNodeInstance::getGraphicBufferUsage(
@@ -367,26 +465,19 @@
     OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
 
     if (err != OMX_ErrorNone) {
-        ALOGE("OMX_GetExtensionIndex %s failed", name);
-
+        CLOG_ERROR(getExtensionIndex, err, "%s", name);
         return StatusFromOMXError(err);
     }
 
-    OMX_VERSIONTYPE ver;
-    ver.s.nVersionMajor = 1;
-    ver.s.nVersionMinor = 0;
-    ver.s.nRevision = 0;
-    ver.s.nStep = 0;
-    GetAndroidNativeBufferUsageParams params = {
-        sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0,
-    };
+    GetAndroidNativeBufferUsageParams params;
+    InitOMXParams(&params);
+    params.nPortIndex = portIndex;
 
     err = OMX_GetParameter(mHandle, index, &params);
-
     if (err != OMX_ErrorNone) {
-        ALOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)",
-                err, err);
-        return UNKNOWN_ERROR;
+        CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", name, index,
+                portString(portIndex), portIndex);
+        return StatusFromOMXError(err);
     }
 
     *usage = params.nUsage;
@@ -398,6 +489,7 @@
         OMX_U32 portIndex,
         OMX_BOOL enable) {
     Mutex::Autolock autolock(mLock);
+    CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u en:%d", portString(portIndex), portIndex, enable);
     return storeMetaDataInBuffers_l(
             portIndex, enable,
             OMX_FALSE /* useGraphicBuffer */, NULL /* usingGraphicBufferInMetadata */);
@@ -424,37 +516,42 @@
                 : OMX_ErrorBadParameter;
     if (err == OMX_ErrorNone) {
         *usingGraphicBufferInMetadata = OMX_TRUE;
+        name = graphicBufferName;
     } else {
-        *usingGraphicBufferInMetadata = OMX_FALSE;
         err = OMX_GetExtensionIndex(mHandle, name, &index);
     }
 
+    OMX_ERRORTYPE xerr = err;
+    if (err == OMX_ErrorNone) {
+        StoreMetaDataInBuffersParams params;
+        InitOMXParams(&params);
+        params.nPortIndex = portIndex;
+        params.bStoreMetaData = enable;
+
+        err = OMX_SetParameter(mHandle, index, &params);
+    }
+
+    // don't log loud error if component does not support metadata mode on the output
     if (err != OMX_ErrorNone) {
-        ALOGE("OMX_GetExtensionIndex %s failed", name);
-        return StatusFromOMXError(err);
-    }
-
-    StoreMetaDataInBuffersParams params;
-    memset(&params, 0, sizeof(params));
-    params.nSize = sizeof(params);
-
-    // Version: 1.0.0.0
-    params.nVersion.s.nVersionMajor = 1;
-
-    params.nPortIndex = portIndex;
-    params.bStoreMetaData = enable;
-    if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
-        ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err);
         *usingGraphicBufferInMetadata = OMX_FALSE;
-        return UNKNOWN_ERROR;
+        if (err == OMX_ErrorUnsupportedIndex && portIndex == kPortIndexOutput) {
+            CLOGW("component does not support metadata mode; using fallback");
+        } else if (xerr != OMX_ErrorNone) {
+            CLOG_ERROR(getExtensionIndex, xerr, "%s", name);
+        } else {
+            CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d GB=%d", name, index,
+                    portString(portIndex), portIndex, enable, useGraphicBuffer);
+        }
     }
-    return err;
+    return StatusFromOMXError(err);
 }
 
 status_t OMXNodeInstance::prepareForAdaptivePlayback(
         OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth,
         OMX_U32 maxFrameHeight) {
     Mutex::Autolock autolock(mLock);
+    CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u",
+            portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
 
     OMX_INDEXTYPE index;
     OMX_STRING name = const_cast<OMX_STRING>(
@@ -462,33 +559,29 @@
 
     OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
     if (err != OMX_ErrorNone) {
-        ALOGW_IF(enable, "OMX_GetExtensionIndex %s failed", name);
+        CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
         return StatusFromOMXError(err);
     }
 
     PrepareForAdaptivePlaybackParams params;
-    params.nSize = sizeof(params);
-    params.nVersion.s.nVersionMajor = 1;
-    params.nVersion.s.nVersionMinor = 0;
-    params.nVersion.s.nRevision = 0;
-    params.nVersion.s.nStep = 0;
-
+    InitOMXParams(&params);
     params.nPortIndex = portIndex;
     params.bEnable = enable;
     params.nMaxFrameWidth = maxFrameWidth;
     params.nMaxFrameHeight = maxFrameHeight;
-    if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
-        ALOGW("OMX_SetParameter failed for PrepareForAdaptivePlayback "
-              "with error %d (0x%08x)", err, err);
-        return UNKNOWN_ERROR;
-    }
-    return err;
+
+    err = OMX_SetParameter(mHandle, index, &params);
+    CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d max=%ux%u", name, index,
+            portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
+    return StatusFromOMXError(err);
 }
 
 status_t OMXNodeInstance::configureVideoTunnelMode(
         OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync,
         native_handle_t **sidebandHandle) {
     Mutex::Autolock autolock(mLock);
+    CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u",
+            portString(portIndex), portIndex, tunneled, audioHwSync);
 
     OMX_INDEXTYPE index;
     OMX_STRING name = const_cast<OMX_STRING>(
@@ -496,36 +589,33 @@
 
     OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
     if (err != OMX_ErrorNone) {
-        ALOGE("configureVideoTunnelMode extension is missing!");
+        CLOG_ERROR_IF(tunneled, getExtensionIndex, err, "%s", name);
         return StatusFromOMXError(err);
     }
 
     ConfigureVideoTunnelModeParams tunnelParams;
-    tunnelParams.nSize = sizeof(tunnelParams);
-    tunnelParams.nVersion.s.nVersionMajor = 1;
-    tunnelParams.nVersion.s.nVersionMinor = 0;
-    tunnelParams.nVersion.s.nRevision = 0;
-    tunnelParams.nVersion.s.nStep = 0;
-
+    InitOMXParams(&tunnelParams);
     tunnelParams.nPortIndex = portIndex;
     tunnelParams.bTunneled = tunneled;
     tunnelParams.nAudioHwSync = audioHwSync;
     err = OMX_SetParameter(mHandle, index, &tunnelParams);
     if (err != OMX_ErrorNone) {
-        ALOGE("configureVideoTunnelMode failed! (err %d).", err);
-        return UNKNOWN_ERROR;
+        CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index,
+                portString(portIndex), portIndex, tunneled, audioHwSync);
+        return StatusFromOMXError(err);
     }
 
     err = OMX_GetParameter(mHandle, index, &tunnelParams);
     if (err != OMX_ErrorNone) {
-        ALOGE("GetVideoTunnelWindow failed! (err %d).", err);
-        return UNKNOWN_ERROR;
+        CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index,
+                portString(portIndex), portIndex, tunneled, audioHwSync);
+        return StatusFromOMXError(err);
     }
     if (sidebandHandle) {
         *sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
     }
 
-    return err;
+    return OK;
 }
 
 status_t OMXNodeInstance::useBuffer(
@@ -542,14 +632,14 @@
             params->size(), static_cast<OMX_U8 *>(params->pointer()));
 
     if (err != OMX_ErrorNone) {
-        ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
+        CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(portIndex, params->size(), params->pointer()));
 
         delete buffer_meta;
         buffer_meta = NULL;
 
         *buffer = 0;
 
-        return UNKNOWN_ERROR;
+        return StatusFromOMXError(err);
     }
 
     CHECK_EQ(header->pAppPrivate, buffer_meta);
@@ -563,6 +653,8 @@
         bufferSource->addCodecBuffer(header);
     }
 
+    CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT(
+            *buffer, portIndex, "%zu@%p", params->size(), params->pointer()));
     return OK;
 }
 
@@ -572,17 +664,14 @@
 
     // port definition
     OMX_PARAM_PORTDEFINITIONTYPE def;
-    def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
-    def.nVersion.s.nVersionMajor = 1;
-    def.nVersion.s.nVersionMinor = 0;
-    def.nVersion.s.nRevision = 0;
-    def.nVersion.s.nStep = 0;
+    InitOMXParams(&def);
     def.nPortIndex = portIndex;
     OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
-    if (err != OMX_ErrorNone)
-    {
-        ALOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__);
-        return err;
+    if (err != OMX_ErrorNone) {
+        OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
+        CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u",
+                asString(index), index, portString(portIndex), portIndex);
+        return UNKNOWN_ERROR;
     }
 
     BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
@@ -600,11 +689,11 @@
             bufferHandle);
 
     if (err != OMX_ErrorNone) {
-        ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
+        CLOG_ERROR(useBuffer, err, BUFFER_FMT(portIndex, "%u@%p", def.nBufferSize, bufferHandle));
         delete bufferMeta;
         bufferMeta = NULL;
         *buffer = 0;
-        return UNKNOWN_ERROR;
+        return StatusFromOMXError(err);
     }
 
     CHECK_EQ(header->pBuffer, bufferHandle);
@@ -613,7 +702,8 @@
     *buffer = makeBufferID(header);
 
     addActiveBuffer(portIndex, *buffer);
-
+    CLOG_BUFFER(useGraphicBuffer2, NEW_BUFFER_FMT(
+            *buffer, portIndex, "%u@%p", def.nBufferSize, bufferHandle));
     return OK;
 }
 
@@ -637,10 +727,8 @@
     OMX_STRING name = const_cast<OMX_STRING>(
         "OMX.google.android.index.useAndroidNativeBuffer");
     OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
-
     if (err != OMX_ErrorNone) {
-        ALOGE("OMX_GetExtensionIndex %s failed", name);
-
+        CLOG_ERROR(getExtensionIndex, err, "%s", name);
         return StatusFromOMXError(err);
     }
 
@@ -661,15 +749,15 @@
     err = OMX_SetParameter(mHandle, index, &params);
 
     if (err != OMX_ErrorNone) {
-        ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err,
-                err);
+        CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u meta=%p GB=%p", name, index,
+                portString(portIndex), portIndex, bufferMeta, graphicBuffer->handle);
 
         delete bufferMeta;
         bufferMeta = NULL;
 
         *buffer = 0;
 
-        return UNKNOWN_ERROR;
+        return StatusFromOMXError(err);
     }
 
     CHECK_EQ(header->pAppPrivate, bufferMeta);
@@ -677,12 +765,13 @@
     *buffer = makeBufferID(header);
 
     addActiveBuffer(portIndex, *buffer);
-
+    CLOG_BUFFER(useGraphicBuffer, NEW_BUFFER_FMT(
+            *buffer, portIndex, "GB=%p", graphicBuffer->handle));
     return OK;
 }
 
 status_t OMXNodeInstance::updateGraphicBufferInMeta(
-        OMX_U32 /* portIndex */, const sp<GraphicBuffer>& graphicBuffer,
+        OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
         OMX::buffer_id buffer) {
     Mutex::Autolock autoLock(mLock);
 
@@ -693,7 +782,8 @@
     bufferMeta->setGraphicBuffer(graphicBuffer);
     metadata->eType = kMetadataBufferTypeGrallocSource;
     metadata->pHandle = graphicBuffer->handle;
-
+    CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p",
+            portString(portIndex), portIndex, buffer, graphicBuffer->handle);
     return OK;
 }
 
@@ -719,19 +809,21 @@
     // Retrieve the width and height of the graphic buffer, set when the
     // codec was configured.
     OMX_PARAM_PORTDEFINITIONTYPE def;
-    def.nSize = sizeof(def);
-    def.nVersion.s.nVersionMajor = 1;
-    def.nVersion.s.nVersionMinor = 0;
-    def.nVersion.s.nRevision = 0;
-    def.nVersion.s.nStep = 0;
+    InitOMXParams(&def);
     def.nPortIndex = portIndex;
     OMX_ERRORTYPE oerr = OMX_GetParameter(
             mHandle, OMX_IndexParamPortDefinition, &def);
-    CHECK(oerr == OMX_ErrorNone);
+    if (oerr != OMX_ErrorNone) {
+        OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
+        CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u",
+                asString(index), index, portString(portIndex), portIndex);
+        return UNKNOWN_ERROR;
+    }
 
     if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) {
-        ALOGE("createInputSurface requires COLOR_FormatSurface "
-              "(AndroidOpaque) color format");
+        CLOGW("createInputSurface requires COLOR_FormatSurface "
+                "(AndroidOpaque) color format instead of %s(%#x)",
+                asString(def.format.video.eColorFormat), def.format.video.eColorFormat);
         return INVALID_OPERATION;
     }
 
@@ -754,9 +846,9 @@
     // flag set).  Seems easier than doing the equivalent from here.
     sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
     if (bufferSource == NULL) {
-        ALOGW("signalEndOfInputStream can only be used with Surface input");
+        CLOGW("signalEndOfInputStream can only be used with Surface input");
         return INVALID_OPERATION;
-    };
+    }
     return bufferSource->signalEndOfInputStream();
 }
 
@@ -773,14 +865,13 @@
             mHandle, &header, portIndex, buffer_meta, size);
 
     if (err != OMX_ErrorNone) {
-        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
-
+        CLOG_ERROR(allocateBuffer, err, BUFFER_FMT(portIndex, "%zu@", size));
         delete buffer_meta;
         buffer_meta = NULL;
 
         *buffer = 0;
 
-        return UNKNOWN_ERROR;
+        return StatusFromOMXError(err);
     }
 
     CHECK_EQ(header->pAppPrivate, buffer_meta);
@@ -794,6 +885,7 @@
     if (bufferSource != NULL && portIndex == kPortIndexInput) {
         bufferSource->addCodecBuffer(header);
     }
+    CLOG_BUFFER(allocateBuffer, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p", size, *buffer_data));
 
     return OK;
 }
@@ -811,14 +903,14 @@
             mHandle, &header, portIndex, buffer_meta, params->size());
 
     if (err != OMX_ErrorNone) {
-        ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
-
+        CLOG_ERROR(allocateBufferWithBackup, err,
+                SIMPLE_BUFFER(portIndex, params->size(), params->pointer()));
         delete buffer_meta;
         buffer_meta = NULL;
 
         *buffer = 0;
 
-        return UNKNOWN_ERROR;
+        return StatusFromOMXError(err);
     }
 
     CHECK_EQ(header->pAppPrivate, buffer_meta);
@@ -832,12 +924,16 @@
         bufferSource->addCodecBuffer(header);
     }
 
+    CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p :> %p",
+            params->size(), params->pointer(), header->pBuffer));
+
     return OK;
 }
 
 status_t OMXNodeInstance::freeBuffer(
         OMX_U32 portIndex, OMX::buffer_id buffer) {
     Mutex::Autolock autoLock(mLock);
+    CLOG_BUFFER(freeBuffer, "%s:%u %#x", portString(portIndex), portIndex, buffer);
 
     removeActiveBuffer(portIndex, buffer);
 
@@ -845,6 +941,7 @@
     BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
 
     OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
+    CLOG_IF_ERROR(freeBuffer, err, "%s:%u %#x", portString(portIndex), portIndex, buffer);
 
     delete buffer_meta;
     buffer_meta = NULL;
@@ -861,8 +958,18 @@
     header->nOffset = 0;
     header->nFlags = 0;
 
-    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
+    {
+        Mutex::Autolock _l(mDebugLock);
+        mOutputBuffersWithCodec.add(header);
+        CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header)));
+    }
 
+    OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
+    if (err != OMX_ErrorNone) {
+        CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header));
+        Mutex::Autolock _l(mDebugLock);
+        mOutputBuffersWithCodec.remove(header);
+    }
     return StatusFromOMXError(err);
 }
 
@@ -875,14 +982,66 @@
     OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
     header->nFilledLen = rangeLength;
     header->nOffset = rangeOffset;
-    header->nFlags = flags;
-    header->nTimeStamp = timestamp;
 
     BufferMeta *buffer_meta =
         static_cast<BufferMeta *>(header->pAppPrivate);
     buffer_meta->CopyToOMX(header);
 
+    return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer);
+}
+
+// log queued buffer activity for the next few input and/or output frames
+// if logging at internal state level
+void OMXNodeInstance::bumpDebugLevel_l(size_t numInputBuffers, size_t numOutputBuffers) {
+    if (DEBUG == ADebug::kDebugInternalState) {
+        DEBUG_BUMP = ADebug::kDebugAll;
+        if (numInputBuffers > 0) {
+            mDebugLevelBumpPendingBuffers[kPortIndexInput] = numInputBuffers;
+        }
+        if (numOutputBuffers > 0) {
+            mDebugLevelBumpPendingBuffers[kPortIndexOutput] = numOutputBuffers;
+        }
+    }
+}
+
+void OMXNodeInstance::unbumpDebugLevel_l(size_t portIndex) {
+    if (mDebugLevelBumpPendingBuffers[portIndex]) {
+        --mDebugLevelBumpPendingBuffers[portIndex];
+    }
+    if (!mDebugLevelBumpPendingBuffers[0]
+            && !mDebugLevelBumpPendingBuffers[1]) {
+        DEBUG_BUMP = DEBUG;
+    }
+}
+
+status_t OMXNodeInstance::emptyBuffer_l(
+        OMX_BUFFERHEADERTYPE *header, OMX_U32 flags, OMX_TICKS timestamp, intptr_t debugAddr) {
+    header->nFlags = flags;
+    header->nTimeStamp = timestamp;
+
+    {
+        Mutex::Autolock _l(mDebugLock);
+        mInputBuffersWithCodec.add(header);
+
+        // bump internal-state debug level for 2 input frames past a buffer with CSD
+        if ((flags & OMX_BUFFERFLAG_CODECCONFIG) != 0) {
+            bumpDebugLevel_l(2 /* numInputBuffers */, 0 /* numOutputBuffers */);
+        }
+
+        CLOG_BUMPED_BUFFER(emptyBuffer, WITH_STATS(FULL_BUFFER(debugAddr, header)));
+    }
+
     OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
+    CLOG_IF_ERROR(emptyBuffer, err, FULL_BUFFER(debugAddr, header));
+
+    {
+        Mutex::Autolock _l(mDebugLock);
+        if (err != OMX_ErrorNone) {
+            mInputBuffersWithCodec.remove(header);
+        } else if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
+            unbumpDebugLevel_l(kPortIndexInput);
+        }
+    }
 
     return StatusFromOMXError(err);
 }
@@ -896,15 +1055,8 @@
 
     header->nFilledLen = rangeLength;
     header->nOffset = rangeOffset;
-    header->nFlags = flags;
-    header->nTimeStamp = timestamp;
 
-    OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
-    if (err != OMX_ErrorNone) {
-        ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err);
-    }
-
-    return StatusFromOMXError(err);
+    return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer);
 }
 
 status_t OMXNodeInstance::getExtensionIndex(
@@ -917,15 +1069,31 @@
     return StatusFromOMXError(err);
 }
 
+inline static const char *asString(IOMX::InternalOptionType i, const char *def = "??") {
+    switch (i) {
+        case IOMX::INTERNAL_OPTION_SUSPEND:           return "SUSPEND";
+        case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
+            return "REPEAT_PREVIOUS_FRAME_DELAY";
+        case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: return "MAX_TIMESTAMP_GAP";
+        case IOMX::INTERNAL_OPTION_MAX_FPS:           return "MAX_FPS";
+        case IOMX::INTERNAL_OPTION_START_TIME:        return "START_TIME";
+        case IOMX::INTERNAL_OPTION_TIME_LAPSE:        return "TIME_LAPSE";
+        default:                                      return def;
+    }
+}
+
 status_t OMXNodeInstance::setInternalOption(
         OMX_U32 portIndex,
         IOMX::InternalOptionType type,
         const void *data,
         size_t size) {
+    CLOG_CONFIG(setInternalOption, "%s(%d): %s:%u %zu@%p",
+            asString(type), type, portString(portIndex), portIndex, size, data);
     switch (type) {
         case IOMX::INTERNAL_OPTION_SUSPEND:
         case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
         case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP:
+        case IOMX::INTERNAL_OPTION_MAX_FPS:
         case IOMX::INTERNAL_OPTION_START_TIME:
         case IOMX::INTERNAL_OPTION_TIME_LAPSE:
         {
@@ -933,6 +1101,7 @@
                 getGraphicBufferSource();
 
             if (bufferSource == NULL || portIndex != kPortIndexInput) {
+                CLOGW("setInternalOption is only for Surface input");
                 return ERROR_UNSUPPORTED;
             }
 
@@ -942,6 +1111,7 @@
                 }
 
                 bool suspend = *(bool *)data;
+                CLOG_CONFIG(setInternalOption, "suspend=%d", suspend);
                 bufferSource->suspend(suspend);
             } else if (type ==
                     IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY){
@@ -950,7 +1120,7 @@
                 }
 
                 int64_t delayUs = *(int64_t *)data;
-
+                CLOG_CONFIG(setInternalOption, "delayUs=%lld", (long long)delayUs);
                 return bufferSource->setRepeatPreviousFrameDelayUs(delayUs);
             } else if (type ==
                     IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP){
@@ -959,21 +1129,34 @@
                 }
 
                 int64_t maxGapUs = *(int64_t *)data;
-
+                CLOG_CONFIG(setInternalOption, "gapUs=%lld", (long long)maxGapUs);
                 return bufferSource->setMaxTimestampGapUs(maxGapUs);
+            } else if (type == IOMX::INTERNAL_OPTION_MAX_FPS) {
+                if (size != sizeof(float)) {
+                    return INVALID_OPERATION;
+                }
+
+                float maxFps = *(float *)data;
+                CLOG_CONFIG(setInternalOption, "maxFps=%f", maxFps);
+                return bufferSource->setMaxFps(maxFps);
             } else if (type == IOMX::INTERNAL_OPTION_START_TIME) {
                 if (size != sizeof(int64_t)) {
                     return INVALID_OPERATION;
                 }
 
                 int64_t skipFramesBeforeUs = *(int64_t *)data;
-
+                CLOG_CONFIG(setInternalOption, "beforeUs=%lld", (long long)skipFramesBeforeUs);
                 bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs);
             } else { // IOMX::INTERNAL_OPTION_TIME_LAPSE
                 if (size != sizeof(int64_t) * 2) {
                     return INVALID_OPERATION;
                 }
 
+                int64_t timePerFrameUs = ((int64_t *)data)[0];
+                int64_t timePerCaptureUs = ((int64_t *)data)[1];
+                CLOG_CONFIG(setInternalOption, "perFrameUs=%lld perCaptureUs=%lld",
+                        (long long)timePerFrameUs, (long long)timePerCaptureUs);
+
                 bufferSource->setTimeLapseUs((int64_t *)data);
             }
 
@@ -992,6 +1175,16 @@
         OMX_BUFFERHEADERTYPE *buffer =
             findBufferHeader(msg.u.extended_buffer_data.buffer);
 
+        {
+            Mutex::Autolock _l(mDebugLock);
+            mOutputBuffersWithCodec.remove(buffer);
+
+            CLOG_BUMPED_BUFFER(
+                    FBD, WITH_STATS(FULL_BUFFER(msg.u.extended_buffer_data.buffer, buffer)));
+
+            unbumpDebugLevel_l(kPortIndexOutput);
+        }
+
         BufferMeta *buffer_meta =
             static_cast<BufferMeta *>(buffer->pAppPrivate);
 
@@ -1007,16 +1200,23 @@
             return;
         }
     } else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
+        OMX_BUFFERHEADERTYPE *buffer =
+            findBufferHeader(msg.u.buffer_data.buffer);
+
+        {
+            Mutex::Autolock _l(mDebugLock);
+            mInputBuffersWithCodec.remove(buffer);
+
+            CLOG_BUMPED_BUFFER(
+                    EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer)));
+        }
+
         if (bufferSource != NULL) {
             // This is one of the buffers used exclusively by
             // GraphicBufferSource.
             // Don't dispatch a message back to ACodec, since it doesn't
             // know that anyone asked to have the buffer emptied and will
             // be very confused.
-
-            OMX_BUFFERHEADERTYPE *buffer =
-                findBufferHeader(msg.u.buffer_data.buffer);
-
             bufferSource->codecBufferEmptied(buffer);
             return;
         }
@@ -1040,6 +1240,43 @@
 // Don't try to acquire mLock here -- in rare circumstances this will hang.
 void OMXNodeInstance::onEvent(
         OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
+    const char *arg1String = "??";
+    const char *arg2String = "??";
+    ADebug::Level level = ADebug::kDebugInternalState;
+
+    switch (event) {
+        case OMX_EventCmdComplete:
+            arg1String = asString((OMX_COMMANDTYPE)arg1);
+            switch (arg1) {
+                case OMX_CommandStateSet:
+                    arg2String = asString((OMX_STATETYPE)arg2);
+                    level = ADebug::kDebugState;
+                    break;
+                case OMX_CommandFlush:
+                case OMX_CommandPortEnable:
+                {
+                    // bump internal-state debug level for 2 input and output frames
+                    Mutex::Autolock _l(mDebugLock);
+                    bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */);
+                }
+                // fall through
+                default:
+                    arg2String = portString(arg2);
+            }
+            break;
+        case OMX_EventError:
+            arg1String = asString((OMX_ERRORTYPE)arg1);
+            level = ADebug::kDebugLifeCycle;
+            break;
+        case OMX_EventPortSettingsChanged:
+            arg2String = asString((OMX_INDEXEXTTYPE)arg2);
+            // fall through
+        default:
+            arg1String = portString(arg1);
+    }
+
+    CLOGI_(level, onEvent, "%s(%x), %s(%x), %s(%x)",
+            asString(event), event, arg1String, arg1, arg2String, arg2);
     const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
 
     if (bufferSource != NULL
@@ -1097,23 +1334,27 @@
     active.mPortIndex = portIndex;
     active.mID = id;
     mActiveBuffers.push(active);
+
+    if (portIndex < NELEM(mNumPortBuffers)) {
+        ++mNumPortBuffers[portIndex];
+    }
 }
 
 void OMXNodeInstance::removeActiveBuffer(
         OMX_U32 portIndex, OMX::buffer_id id) {
-    bool found = false;
     for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
         if (mActiveBuffers[i].mPortIndex == portIndex
-            && mActiveBuffers[i].mID == id) {
-            found = true;
+                && mActiveBuffers[i].mID == id) {
             mActiveBuffers.removeItemsAt(i);
-            break;
+
+            if (portIndex < NELEM(mNumPortBuffers)) {
+                --mNumPortBuffers[portIndex];
+            }
+            return;
         }
     }
 
-    if (!found) {
-        ALOGW("Attempt to remove an active buffer we know nothing about...");
-    }
+     CLOGW("Attempt to remove an active buffer [%#x] we know nothing about...", id);
 }
 
 void OMXNodeInstance::freeActiveBuffers() {
@@ -1134,7 +1375,7 @@
     OMX::buffer_id buffer;
     do { // handle the very unlikely case of ID overflow
         if (++mBufferIDCount == 0) {
-           ++mBufferIDCount;
+            ++mBufferIDCount;
         }
         buffer = (OMX::buffer_id)mBufferIDCount;
     } while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0);
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
index 4999663..801a1bd 100644
--- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -58,7 +58,7 @@
         OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data) {
     CHECK(data == NULL);
 
-    sp<AMessage> msg = new AMessage(kWhatSendCommand, mHandler->id());
+    sp<AMessage> msg = new AMessage(kWhatSendCommand, mHandler);
     msg->setInt32("cmd", cmd);
     msg->setInt32("param", param);
     msg->post();
@@ -152,28 +152,28 @@
             OMX_PARAM_PORTDEFINITIONTYPE *defParams =
                 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
 
-            if (defParams->nPortIndex >= mPorts.size()
-                    || defParams->nSize
-                            != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
-                return OMX_ErrorUndefined;
+            if (defParams->nPortIndex >= mPorts.size()) {
+                return OMX_ErrorBadPortIndex;
+            }
+            if (defParams->nSize != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
+                return OMX_ErrorUnsupportedSetting;
             }
 
             PortInfo *port =
                 &mPorts.editItemAt(defParams->nPortIndex);
 
-            if (defParams->nBufferSize != port->mDef.nBufferSize) {
-                CHECK_GE(defParams->nBufferSize, port->mDef.nBufferSize);
+            // default behavior is that we only allow buffer size to increase
+            if (defParams->nBufferSize > port->mDef.nBufferSize) {
                 port->mDef.nBufferSize = defParams->nBufferSize;
             }
 
-            if (defParams->nBufferCountActual
-                    != port->mDef.nBufferCountActual) {
-                CHECK_GE(defParams->nBufferCountActual,
-                         port->mDef.nBufferCountMin);
-
-                port->mDef.nBufferCountActual = defParams->nBufferCountActual;
+            if (defParams->nBufferCountActual < port->mDef.nBufferCountMin) {
+                ALOGW("component requires at least %u buffers (%u requested)",
+                        port->mDef.nBufferCountMin, defParams->nBufferCountActual);
+                return OMX_ErrorUnsupportedSetting;
             }
 
+            port->mDef.nBufferCountActual = defParams->nBufferCountActual;
             return OMX_ErrorNone;
         }
 
@@ -307,7 +307,7 @@
 
 OMX_ERRORTYPE SimpleSoftOMXComponent::emptyThisBuffer(
         OMX_BUFFERHEADERTYPE *buffer) {
-    sp<AMessage> msg = new AMessage(kWhatEmptyThisBuffer, mHandler->id());
+    sp<AMessage> msg = new AMessage(kWhatEmptyThisBuffer, mHandler);
     msg->setPointer("header", buffer);
     msg->post();
 
@@ -316,7 +316,7 @@
 
 OMX_ERRORTYPE SimpleSoftOMXComponent::fillThisBuffer(
         OMX_BUFFERHEADERTYPE *buffer) {
-    sp<AMessage> msg = new AMessage(kWhatFillThisBuffer, mHandler->id());
+    sp<AMessage> msg = new AMessage(kWhatFillThisBuffer, mHandler);
     msg->setPointer("header", buffer);
     msg->post();
 
diff --git a/media/libstagefright/omx/SoftOMXComponent.cpp b/media/libstagefright/omx/SoftOMXComponent.cpp
index 646cd32..df978f8 100644
--- a/media/libstagefright/omx/SoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftOMXComponent.cpp
@@ -283,7 +283,7 @@
 
 OMX_ERRORTYPE SoftOMXComponent::getExtensionIndex(
         const char * /* name */, OMX_INDEXTYPE * /* index */) {
-    return OMX_ErrorUndefined;
+    return OMX_ErrorUnsupportedIndex;
 }
 
 OMX_ERRORTYPE SoftOMXComponent::useBuffer(
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 2f83610..4ce165b 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -26,6 +26,7 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 
 namespace android {
@@ -61,6 +62,8 @@
         mCropWidth(width),
         mCropHeight(height),
         mOutputPortSettingsChange(NONE),
+        mMinInputBufferSize(384), // arbitrary, using one uncompressed macroblock
+        mMinCompressionRatio(1),  // max input size is normally the output size
         mComponentRole(componentRole),
         mCodingType(codingType),
         mProfileLevels(profileLevels),
@@ -71,7 +74,11 @@
         OMX_U32 numInputBuffers,
         OMX_U32 inputBufferSize,
         OMX_U32 numOutputBuffers,
-        const char *mimeType) {
+        const char *mimeType,
+        OMX_U32 minCompressionRatio) {
+    mMinInputBufferSize = inputBufferSize;
+    mMinCompressionRatio = minCompressionRatio;
+
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
 
@@ -120,27 +127,32 @@
 
     addPort(def);
 
-    updatePortDefinitions();
+    updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */);
 }
 
-void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop) {
-    OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
-    def->format.video.nFrameWidth = mWidth;
-    def->format.video.nFrameHeight = mHeight;
-    def->format.video.nStride = def->format.video.nFrameWidth;
-    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+void SoftVideoDecoderOMXComponent::updatePortDefinitions(bool updateCrop, bool updateInputSize) {
+    OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef;
+    outDef->format.video.nFrameWidth = outputBufferWidth();
+    outDef->format.video.nFrameHeight = outputBufferHeight();
+    outDef->format.video.nStride = outDef->format.video.nFrameWidth;
+    outDef->format.video.nSliceHeight = outDef->format.video.nFrameHeight;
 
-    def->nBufferSize = def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2;
+    outDef->nBufferSize =
+        (outDef->format.video.nStride * outDef->format.video.nSliceHeight * 3) / 2;
 
-    def = &editPortInfo(kOutputPortIndex)->mDef;
-    def->format.video.nFrameWidth = outputBufferWidth();
-    def->format.video.nFrameHeight = outputBufferHeight();
-    def->format.video.nStride = def->format.video.nFrameWidth;
-    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+    OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef;
+    inDef->format.video.nFrameWidth = mWidth;
+    inDef->format.video.nFrameHeight = mHeight;
+    // input port is compressed, hence it has no stride
+    inDef->format.video.nStride = 0;
+    inDef->format.video.nSliceHeight = 0;
 
-    def->nBufferSize =
-            (def->format.video.nFrameWidth *
-             def->format.video.nFrameHeight * 3) / 2;
+    // when output format changes, input buffer size does not actually change
+    if (updateInputSize) {
+        inDef->nBufferSize = max(
+                outDef->nBufferSize / mMinCompressionRatio,
+                max(mMinInputBufferSize, inDef->nBufferSize));
+    }
 
     if (updateCrop) {
         mCropLeft = 0;
@@ -169,7 +181,8 @@
     bool strideChanged = false;
     if (fakeStride) {
         OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
-        if (def->format.video.nStride != width || def->format.video.nSliceHeight != height) {
+        if (def->format.video.nStride != (OMX_S32)width
+                || def->format.video.nSliceHeight != (OMX_U32)height) {
             strideChanged = true;
         }
     }
@@ -252,7 +265,7 @@
                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
 
             if (formatParams->nPortIndex > kMaxPortIndex) {
-                return OMX_ErrorUndefined;
+                return OMX_ErrorBadPortIndex;
             }
 
             if (formatParams->nIndex != 0) {
@@ -324,13 +337,25 @@
                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
 
             if (formatParams->nPortIndex > kMaxPortIndex) {
-                return OMX_ErrorUndefined;
+                return OMX_ErrorBadPortIndex;
             }
 
             if (formatParams->nIndex != 0) {
                 return OMX_ErrorNoMore;
             }
 
+            if (formatParams->nPortIndex == kInputPortIndex) {
+                if (formatParams->eCompressionFormat != mCodingType
+                        || formatParams->eColorFormat != OMX_COLOR_FormatUnused) {
+                    return OMX_ErrorUnsupportedSetting;
+                }
+            } else {
+                if (formatParams->eCompressionFormat != OMX_VIDEO_CodingUnused
+                        || formatParams->eColorFormat != OMX_COLOR_FormatYUV420Planar) {
+                    return OMX_ErrorUnsupportedSetting;
+                }
+            }
+
             return OMX_ErrorNone;
         }
 
@@ -348,7 +373,7 @@
                 mAdaptiveMaxWidth = 0;
                 mAdaptiveMaxHeight = 0;
             }
-            updatePortDefinitions();
+            updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */);
             return OMX_ErrorNone;
         }
 
@@ -365,23 +390,21 @@
             uint32_t newHeight = video_def->nFrameHeight;
             if (newWidth != oldWidth || newHeight != oldHeight) {
                 bool outputPort = (newParams->nPortIndex == kOutputPortIndex);
-                def->format.video.nFrameWidth =
-                    (mIsAdaptive && outputPort) ? mAdaptiveMaxWidth : newWidth;
-                def->format.video.nFrameHeight =
-                    (mIsAdaptive && outputPort) ? mAdaptiveMaxHeight : newHeight;
-                def->format.video.nStride = def->format.video.nFrameWidth;
-                def->format.video.nSliceHeight = def->format.video.nFrameHeight;
-                def->nBufferSize =
-                    def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2;
                 if (outputPort) {
+                    // only update (essentially crop) if size changes
                     mWidth = newWidth;
                     mHeight = newHeight;
-                    mCropLeft = 0;
-                    mCropTop = 0;
-                    mCropWidth = newWidth;
-                    mCropHeight = newHeight;
+
+                    updatePortDefinitions(true /* updateCrop */, true /* updateInputSize */);
+                    // reset buffer size based on frame size
+                    newParams->nBufferSize = def->nBufferSize;
+                } else {
+                    // For input port, we only set nFrameWidth and nFrameHeight. Buffer size
+                    // is updated when configuring the output port using the max-frame-size,
+                    // though client can still request a larger size.
+                    def->format.video.nFrameWidth = newWidth;
+                    def->format.video.nFrameHeight = newHeight;
                 }
-                newParams->nBufferSize = def->nBufferSize;
             }
             return SimpleSoftOMXComponent::internalSetParameter(index, params);
         }
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index 70ec6e4..d4d6217 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -19,6 +19,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "SoftVideoEncoderOMXComponent"
 #include <utils/Log.h>
+#include <utils/misc.h>
 
 #include "include/SoftVideoEncoderOMXComponent.h"
 
@@ -27,6 +28,7 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/MediaDefs.h>
 
 #include <ui/GraphicBuffer.h>
@@ -34,13 +36,316 @@
 
 namespace android {
 
+const static OMX_COLOR_FORMATTYPE kSupportedColorFormats[] = {
+    OMX_COLOR_FormatYUV420Planar,
+    OMX_COLOR_FormatYUV420SemiPlanar,
+    OMX_COLOR_FormatAndroidOpaque
+};
+
+template<class T>
+static void InitOMXParams(T *params) {
+    params->nSize = sizeof(T);
+    params->nVersion.s.nVersionMajor = 1;
+    params->nVersion.s.nVersionMinor = 0;
+    params->nVersion.s.nRevision = 0;
+    params->nVersion.s.nStep = 0;
+}
+
 SoftVideoEncoderOMXComponent::SoftVideoEncoderOMXComponent(
         const char *name,
+        const char *componentRole,
+        OMX_VIDEO_CODINGTYPE codingType,
+        const CodecProfileLevel *profileLevels,
+        size_t numProfileLevels,
+        int32_t width,
+        int32_t height,
         const OMX_CALLBACKTYPE *callbacks,
         OMX_PTR appData,
         OMX_COMPONENTTYPE **component)
     : SimpleSoftOMXComponent(name, callbacks, appData, component),
-      mGrallocModule(NULL) {
+      mInputDataIsMeta(false),
+      mWidth(width),
+      mHeight(height),
+      mBitrate(192000),
+      mFramerate(30 << 16), // Q16 format
+      mColorFormat(OMX_COLOR_FormatYUV420Planar),
+      mGrallocModule(NULL),
+      mMinOutputBufferSize(384), // arbitrary, using one uncompressed macroblock
+      mMinCompressionRatio(1),   // max output size is normally the input size
+      mComponentRole(componentRole),
+      mCodingType(codingType),
+      mProfileLevels(profileLevels),
+      mNumProfileLevels(numProfileLevels) {
+}
+
+void SoftVideoEncoderOMXComponent::initPorts(
+        OMX_U32 numInputBuffers, OMX_U32 numOutputBuffers, OMX_U32 outputBufferSize,
+        const char *mime, OMX_U32 minCompressionRatio) {
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+
+    mMinOutputBufferSize = outputBufferSize;
+    mMinCompressionRatio = minCompressionRatio;
+
+    InitOMXParams(&def);
+
+    def.nPortIndex = kInputPortIndex;
+    def.eDir = OMX_DirInput;
+    def.nBufferCountMin = numInputBuffers;
+    def.nBufferCountActual = def.nBufferCountMin;
+    def.bEnabled = OMX_TRUE;
+    def.bPopulated = OMX_FALSE;
+    def.eDomain = OMX_PortDomainVideo;
+    def.bBuffersContiguous = OMX_FALSE;
+    def.format.video.pNativeRender = NULL;
+    def.format.video.nFrameWidth = mWidth;
+    def.format.video.nFrameHeight = mHeight;
+    def.format.video.nStride = def.format.video.nFrameWidth;
+    def.format.video.nSliceHeight = def.format.video.nFrameHeight;
+    def.format.video.nBitrate = 0;
+    // frameRate is in Q16 format.
+    def.format.video.xFramerate = mFramerate;
+    def.format.video.bFlagErrorConcealment = OMX_FALSE;
+    def.nBufferAlignment = kInputBufferAlignment;
+    def.format.video.cMIMEType = const_cast<char *>("video/raw");
+    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+    def.format.video.eColorFormat = mColorFormat;
+    def.format.video.pNativeWindow = NULL;
+    // buffersize set in updatePortParams
+
+    addPort(def);
+
+    InitOMXParams(&def);
+
+    def.nPortIndex = kOutputPortIndex;
+    def.eDir = OMX_DirOutput;
+    def.nBufferCountMin = numOutputBuffers;
+    def.nBufferCountActual = def.nBufferCountMin;
+    def.bEnabled = OMX_TRUE;
+    def.bPopulated = OMX_FALSE;
+    def.eDomain = OMX_PortDomainVideo;
+    def.bBuffersContiguous = OMX_FALSE;
+    def.format.video.pNativeRender = NULL;
+    def.format.video.nFrameWidth = mWidth;
+    def.format.video.nFrameHeight = mHeight;
+    def.format.video.nStride = 0;
+    def.format.video.nSliceHeight = 0;
+    def.format.video.nBitrate = mBitrate;
+    def.format.video.xFramerate = 0 << 16;
+    def.format.video.bFlagErrorConcealment = OMX_FALSE;
+    def.nBufferAlignment = kOutputBufferAlignment;
+    def.format.video.cMIMEType = const_cast<char *>(mime);
+    def.format.video.eCompressionFormat = mCodingType;
+    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
+    def.format.video.pNativeWindow = NULL;
+    // buffersize set in updatePortParams
+
+    addPort(def);
+
+    updatePortParams();
+}
+
+void SoftVideoEncoderOMXComponent::updatePortParams() {
+    OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef;
+    inDef->format.video.nFrameWidth = mWidth;
+    inDef->format.video.nFrameHeight = mHeight;
+    inDef->format.video.nStride = inDef->format.video.nFrameWidth;
+    inDef->format.video.nSliceHeight = inDef->format.video.nFrameHeight;
+    inDef->format.video.xFramerate = mFramerate;
+    inDef->format.video.eColorFormat = mColorFormat;
+    uint32_t rawBufferSize =
+        inDef->format.video.nStride * inDef->format.video.nSliceHeight * 3 / 2;
+    if (inDef->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
+        inDef->nBufferSize = 4 + max(sizeof(buffer_handle_t), sizeof(GraphicBuffer *));
+    } else {
+        inDef->nBufferSize = rawBufferSize;
+    }
+
+    OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef;
+    outDef->format.video.nFrameWidth = mWidth;
+    outDef->format.video.nFrameHeight = mHeight;
+    outDef->format.video.nBitrate = mBitrate;
+
+    outDef->nBufferSize = max(mMinOutputBufferSize, rawBufferSize / mMinCompressionRatio);
+}
+
+OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetPortParams(
+        const OMX_PARAM_PORTDEFINITIONTYPE *port) {
+    if (port->nPortIndex == kInputPortIndex) {
+        mWidth = port->format.video.nFrameWidth;
+        mHeight = port->format.video.nFrameHeight;
+
+        // xFramerate comes in Q16 format, in frames per second unit
+        mFramerate = port->format.video.xFramerate;
+
+        if (port->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused
+                || (port->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar
+                        && port->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar
+                        && port->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
+            return OMX_ErrorUnsupportedSetting;
+        }
+
+        mColorFormat = port->format.video.eColorFormat;
+    } else if (port->nPortIndex == kOutputPortIndex) {
+        if (port->format.video.eCompressionFormat != mCodingType
+                || port->format.video.eColorFormat != OMX_COLOR_FormatUnused) {
+            return OMX_ErrorUnsupportedSetting;
+        }
+
+        mBitrate = port->format.video.nBitrate;
+    } else {
+        return OMX_ErrorBadPortIndex;
+    }
+
+    updatePortParams();
+    return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetParameter(
+        OMX_INDEXTYPE index, const OMX_PTR param) {
+    // can include extension index OMX_INDEXEXTTYPE
+    const int32_t indexFull = index;
+
+    switch (indexFull) {
+        case OMX_IndexParamVideoErrorCorrection:
+        {
+            return OMX_ErrorNotImplemented;
+        }
+
+        case OMX_IndexParamStandardComponentRole:
+        {
+            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+                (const OMX_PARAM_COMPONENTROLETYPE *)param;
+
+            if (strncmp((const char *)roleParams->cRole,
+                        mComponentRole,
+                        OMX_MAX_STRINGNAME_SIZE - 1)) {
+                return OMX_ErrorUnsupportedSetting;
+            }
+
+            return OMX_ErrorNone;
+        }
+
+        case OMX_IndexParamPortDefinition:
+        {
+            OMX_ERRORTYPE err = internalSetPortParams((const OMX_PARAM_PORTDEFINITIONTYPE *)param);
+
+            if (err != OMX_ErrorNone) {
+                return err;
+            }
+
+            return SimpleSoftOMXComponent::internalSetParameter(index, param);
+        }
+
+        case OMX_IndexParamVideoPortFormat:
+        {
+            const OMX_VIDEO_PARAM_PORTFORMATTYPE* format =
+                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
+
+            if (format->nPortIndex == kInputPortIndex) {
+                if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
+                    format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
+                    format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
+                    mColorFormat = format->eColorFormat;
+
+                    updatePortParams();
+                    return OMX_ErrorNone;
+                } else {
+                    ALOGE("Unsupported color format %i", format->eColorFormat);
+                    return OMX_ErrorUnsupportedSetting;
+                }
+            } else if (format->nPortIndex == kOutputPortIndex) {
+                if (format->eCompressionFormat == mCodingType) {
+                    return OMX_ErrorNone;
+                } else {
+                    return OMX_ErrorUnsupportedSetting;
+                }
+            } else {
+                return OMX_ErrorBadPortIndex;
+            }
+        }
+
+        case kStoreMetaDataExtensionIndex:
+        {
+            // storeMetaDataInBuffers
+            const StoreMetaDataInBuffersParams *storeParam =
+                (const StoreMetaDataInBuffersParams *)param;
+
+            if (storeParam->nPortIndex == kOutputPortIndex) {
+                return storeParam->bStoreMetaData ? OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
+            } else if (storeParam->nPortIndex != kInputPortIndex) {
+                return OMX_ErrorBadPortIndex;
+            }
+
+            mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE);
+            if (mInputDataIsMeta) {
+                mColorFormat = OMX_COLOR_FormatAndroidOpaque;
+            } else if (mColorFormat == OMX_COLOR_FormatAndroidOpaque) {
+                mColorFormat = OMX_COLOR_FormatYUV420Planar;
+            }
+            updatePortParams();
+            return OMX_ErrorNone;
+        }
+
+        default:
+            return SimpleSoftOMXComponent::internalSetParameter(index, param);
+    }
+}
+
+OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalGetParameter(
+        OMX_INDEXTYPE index, OMX_PTR param) {
+    switch (index) {
+        case OMX_IndexParamVideoErrorCorrection:
+        {
+            return OMX_ErrorNotImplemented;
+        }
+
+        case OMX_IndexParamVideoPortFormat:
+        {
+            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
+                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
+
+            if (formatParams->nPortIndex == kInputPortIndex) {
+                if (formatParams->nIndex >= NELEM(kSupportedColorFormats)) {
+                    return OMX_ErrorNoMore;
+                }
+
+                // Color formats, in order of preference
+                formatParams->eColorFormat = kSupportedColorFormats[formatParams->nIndex];
+                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
+                formatParams->xFramerate = mFramerate;
+                return OMX_ErrorNone;
+            } else if (formatParams->nPortIndex == kOutputPortIndex) {
+                formatParams->eCompressionFormat = mCodingType;
+                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
+                formatParams->xFramerate = 0;
+                return OMX_ErrorNone;
+            } else {
+                return OMX_ErrorBadPortIndex;
+            }
+        }
+
+        case OMX_IndexParamVideoProfileLevelQuerySupported:
+        {
+            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
+                  (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) param;
+
+            if (profileLevel->nPortIndex != kOutputPortIndex) {
+                ALOGE("Invalid port index: %u", profileLevel->nPortIndex);
+                return OMX_ErrorUnsupportedIndex;
+            }
+
+            if (profileLevel->nProfileIndex >= mNumProfileLevels) {
+                return OMX_ErrorNoMore;
+            }
+
+            profileLevel->eProfile = mProfileLevels[profileLevel->nProfileIndex].mProfile;
+            profileLevel->eLevel   = mProfileLevels[profileLevel->nProfileIndex].mLevel;
+            return OMX_ErrorNone;
+        }
+
+        default:
+            return SimpleSoftOMXComponent::internalGetParameter(index, param);
+    }
 }
 
 // static
diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk
index 447b29e..9be637a 100644
--- a/media/libstagefright/omx/tests/Android.mk
+++ b/media/libstagefright/omx/tests/Android.mk
@@ -20,3 +20,21 @@
 LOCAL_32_BIT_ONLY := true
 
 include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := FrameDropper_test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+	FrameDropper_test.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+	libstagefright_omx \
+	libutils \
+
+LOCAL_C_INCLUDES := \
+	frameworks/av/media/libstagefright/omx \
+
+include $(BUILD_NATIVE_TEST)
diff --git a/media/libstagefright/omx/tests/FrameDropper_test.cpp b/media/libstagefright/omx/tests/FrameDropper_test.cpp
new file mode 100644
index 0000000..4ac72c4
--- /dev/null
+++ b/media/libstagefright/omx/tests/FrameDropper_test.cpp
@@ -0,0 +1,136 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "FrameDropper_test"
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+
+#include "FrameDropper.h"
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+struct TestFrame {
+  int64_t timeUs;
+  bool shouldDrop;
+};
+
+static const TestFrame testFrames20Fps[] = {
+    {1000000, false}, {1050000, false}, {1100000, false}, {1150000, false},
+    {1200000, false}, {1250000, false}, {1300000, false}, {1350000, false},
+    {1400000, false}, {1450000, false}, {1500000, false}, {1550000, false},
+    {1600000, false}, {1650000, false}, {1700000, false}, {1750000, false},
+    {1800000, false}, {1850000, false}, {1900000, false}, {1950000, false},
+};
+
+static const TestFrame testFrames30Fps[] = {
+    {1000000, false}, {1033333, false}, {1066667, false}, {1100000, false},
+    {1133333, false}, {1166667, false}, {1200000, false}, {1233333, false},
+    {1266667, false}, {1300000, false}, {1333333, false}, {1366667, false},
+    {1400000, false}, {1433333, false}, {1466667, false}, {1500000, false},
+    {1533333, false}, {1566667, false}, {1600000, false}, {1633333, false},
+};
+
+static const TestFrame testFrames40Fps[] = {
+    {1000000, false}, {1025000, true}, {1050000, false}, {1075000, false},
+    {1100000, false}, {1125000, true}, {1150000, false}, {1175000, false},
+    {1200000, false}, {1225000, true}, {1250000, false}, {1275000, false},
+    {1300000, false}, {1325000, true}, {1350000, false}, {1375000, false},
+    {1400000, false}, {1425000, true}, {1450000, false}, {1475000, false},
+};
+
+static const TestFrame testFrames60Fps[] = {
+    {1000000, false}, {1016667, true}, {1033333, false}, {1050000, true},
+    {1066667, false}, {1083333, true}, {1100000, false}, {1116667, true},
+    {1133333, false}, {1150000, true}, {1166667, false}, {1183333, true},
+    {1200000, false}, {1216667, true}, {1233333, false}, {1250000, true},
+    {1266667, false}, {1283333, true}, {1300000, false}, {1316667, true},
+};
+
+static const TestFrame testFramesVariableFps[] = {
+    // 40fps
+    {1000000, false}, {1025000, true}, {1050000, false}, {1075000, false},
+    {1100000, false}, {1125000, true}, {1150000, false}, {1175000, false},
+    {1200000, false}, {1225000, true}, {1250000, false}, {1275000, false},
+    {1300000, false}, {1325000, true}, {1350000, false}, {1375000, false},
+    {1400000, false}, {1425000, true}, {1450000, false}, {1475000, false},
+    // a timestamp jump plus switch to 20fps
+    {2000000, false}, {2050000, false}, {2100000, false}, {2150000, false},
+    {2200000, false}, {2250000, false}, {2300000, false}, {2350000, false},
+    {2400000, false}, {2450000, false}, {2500000, false}, {2550000, false},
+    {2600000, false}, {2650000, false}, {2700000, false}, {2750000, false},
+    {2800000, false}, {2850000, false}, {2900000, false}, {2950000, false},
+    // 60fps
+    {2966667, false}, {2983333, true}, {3000000, false}, {3016667, true},
+    {3033333, false}, {3050000, true}, {3066667, false}, {3083333, true},
+    {3100000, false}, {3116667, true}, {3133333, false}, {3150000, true},
+    {3166667, false}, {3183333, true}, {3200000, false}, {3216667, true},
+    {3233333, false}, {3250000, true}, {3266667, false}, {3283333, true},
+};
+
+static const int kMaxTestJitterUs = 2000;
+// return one of 1000, 0, -1000 as jitter.
+static int GetJitter(size_t i) {
+    return (1 - (i % 3)) * (kMaxTestJitterUs / 2);
+}
+
+class FrameDropperTest : public ::testing::Test {
+public:
+    FrameDropperTest() : mFrameDropper(new FrameDropper()) {
+        EXPECT_EQ(OK, mFrameDropper->setMaxFrameRate(30.0));
+    }
+
+protected:
+    void RunTest(const TestFrame* frames, size_t size) {
+        for (size_t i = 0; i < size; ++i) {
+            int jitter = GetJitter(i);
+            int64_t testTimeUs = frames[i].timeUs + jitter;
+            printf("time %lld, testTime %lld, jitter %d\n", frames[i].timeUs, testTimeUs, jitter);
+            EXPECT_EQ(frames[i].shouldDrop, mFrameDropper->shouldDrop(testTimeUs));
+        }
+    }
+
+    sp<FrameDropper> mFrameDropper;
+};
+
+TEST_F(FrameDropperTest, TestInvalidMaxFrameRate) {
+    EXPECT_NE(OK, mFrameDropper->setMaxFrameRate(-1.0));
+    EXPECT_NE(OK, mFrameDropper->setMaxFrameRate(0));
+}
+
+TEST_F(FrameDropperTest, Test20Fps) {
+    RunTest(testFrames20Fps, ARRAY_SIZE(testFrames20Fps));
+}
+
+TEST_F(FrameDropperTest, Test30Fps) {
+    RunTest(testFrames30Fps, ARRAY_SIZE(testFrames30Fps));
+}
+
+TEST_F(FrameDropperTest, Test40Fps) {
+    RunTest(testFrames40Fps, ARRAY_SIZE(testFrames40Fps));
+}
+
+TEST_F(FrameDropperTest, Test60Fps) {
+    RunTest(testFrames60Fps, ARRAY_SIZE(testFrames60Fps));
+}
+
+TEST_F(FrameDropperTest, TestVariableFps) {
+    RunTest(testFramesVariableFps, ARRAY_SIZE(testFramesVariableFps));
+}
+
+} // namespace android
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index f4dfd6b..67ff145 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -253,29 +253,6 @@
     return MediaExtractor::Create(source);
 }
 
-static sp<MediaSource> MakeSource(
-        const char *uri,
-        const char *mimeType) {
-    sp<MediaExtractor> extractor = CreateExtractorFromURI(uri);
-
-    if (extractor == NULL) {
-        return NULL;
-    }
-
-    for (size_t i = 0; i < extractor->countTracks(); ++i) {
-        sp<MetaData> meta = extractor->getTrackMetaData(i);
-
-        const char *trackMIME;
-        CHECK(meta->findCString(kKeyMIMEType, &trackMIME));
-
-        if (!strcasecmp(trackMIME, mimeType)) {
-            return extractor->getTrack(i);
-        }
-    }
-
-    return NULL;
-}
-
 status_t Harness::testStateTransitions(
         const char *componentName, const char *componentRole) {
     if (strncmp(componentName, "OMX.", 4)) {
diff --git a/media/libstagefright/rtsp/AAMRAssembler.cpp b/media/libstagefright/rtsp/AAMRAssembler.cpp
index 9e8725a..bb2a238 100644
--- a/media/libstagefright/rtsp/AAMRAssembler.cpp
+++ b/media/libstagefright/rtsp/AAMRAssembler.cpp
@@ -143,8 +143,8 @@
         return MALFORMED_PACKET;
     }
 
-    unsigned payloadHeader = buffer->data()[0];
-    unsigned CMR = payloadHeader >> 4;
+    unsigned payloadHeader __unused = buffer->data()[0];
+    unsigned CMR __unused = payloadHeader >> 4;
 
     Vector<uint8_t> tableOfContents;
 
diff --git a/media/libstagefright/rtsp/AMPEG2TSAssembler.h b/media/libstagefright/rtsp/AMPEG2TSAssembler.h
index 712e18e..f39c2b5 100644
--- a/media/libstagefright/rtsp/AMPEG2TSAssembler.h
+++ b/media/libstagefright/rtsp/AMPEG2TSAssembler.h
@@ -24,7 +24,7 @@
 
 struct AMessage;
 struct AString;
-struct MetaData;
+class MetaData;
 
 struct AMPEG2TSAssembler : public ARTPAssembler {
     AMPEG2TSAssembler(
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
index aa8ffc6..1f76068 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -108,7 +108,7 @@
 static status_t parseGASpecificConfig(
         ABitReader *bits,
         unsigned audioObjectType, unsigned channelConfiguration) {
-    unsigned frameLengthFlag = bits->getBits(1);
+    unsigned frameLengthFlag __unused = bits->getBits(1);
     unsigned dependsOnCoreCoder = bits->getBits(1);
     if (dependsOnCoreCoder) {
         /* unsigned coreCoderDelay = */bits->getBits(1);
@@ -217,7 +217,7 @@
                 // Apparently an extension is always considered an even
                 // multiple of 8 bits long.
 
-                ALOGI("Skipping %d bits after sync extension",
+                ALOGI("Skipping %zu bits after sync extension",
                      8 - (numBitsInExtension & 7));
 
                 bits->skipBits(8 - (numBitsInExtension & 7));
@@ -422,7 +422,7 @@
     }
 
     if (offset < buffer->size()) {
-        ALOGI("ignoring %d bytes of trailing data", buffer->size() - offset);
+        ALOGI("ignoring %zu bytes of trailing data", buffer->size() - offset);
     }
     CHECK_LE(offset, buffer->size());
 
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
index 7eb6542..156004c 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -360,7 +360,7 @@
         }
 
         if (offset != buffer->size()) {
-            ALOGW("potentially malformed packet (offset %d, size %d)",
+            ALOGW("potentially malformed packet (offset %zu, size %zu)",
                     offset, buffer->size());
         }
     }
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 09f52bc..cfafaa7 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -279,8 +279,6 @@
     // be encoded.
     CHECK_LT(20 + config->size(), 128u);
 
-    const uint8_t *data = config->data();
-
     static const uint8_t kStaticESDS[] = {
         0x03, 22,
         0x00, 0x00,     // ES_ID
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 372fbe9..a86ab74 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -82,7 +82,7 @@
         size_t index,
         const sp<AMessage> &notify,
         bool injected) {
-    sp<AMessage> msg = new AMessage(kWhatAddStream, id());
+    sp<AMessage> msg = new AMessage(kWhatAddStream, this);
     msg->setInt32("rtp-socket", rtpSocket);
     msg->setInt32("rtcp-socket", rtcpSocket);
     msg->setObject("session-desc", sessionDesc);
@@ -93,7 +93,7 @@
 }
 
 void ARTPConnection::removeStream(int rtpSocket, int rtcpSocket) {
-    sp<AMessage> msg = new AMessage(kWhatRemoveStream, id());
+    sp<AMessage> msg = new AMessage(kWhatRemoveStream, this);
     msg->setInt32("rtp-socket", rtpSocket);
     msg->setInt32("rtcp-socket", rtcpSocket);
     msg->post();
@@ -233,7 +233,7 @@
         return;
     }
 
-    sp<AMessage> msg = new AMessage(kWhatPollStreams, id());
+    sp<AMessage> msg = new AMessage(kWhatPollStreams, this);
     msg->post();
 
     mPollEventPending = true;
@@ -639,7 +639,7 @@
 }
 
 void ARTPConnection::injectPacket(int index, const sp<ABuffer> &buffer) {
-    sp<AMessage> msg = new AMessage(kWhatInjectPacket, id());
+    sp<AMessage> msg = new AMessage(kWhatInjectPacket, this);
     msg->setInt32("index", index);
     msg->setBuffer("buffer", buffer);
     msg->post();
@@ -664,11 +664,10 @@
 
     StreamInfo *s = &*it;
 
-    status_t err;
     if (it->mRTPSocket == index) {
-        err = parseRTP(s, buffer);
+        parseRTP(s, buffer);
     } else {
-        err = parseRTCP(s, buffer);
+        parseRTCP(s, buffer);
     }
 }
 
diff --git a/media/libstagefright/rtsp/ARTPSession.cpp b/media/libstagefright/rtsp/ARTPSession.cpp
index ba4e33c..e5acb06 100644
--- a/media/libstagefright/rtsp/ARTPSession.cpp
+++ b/media/libstagefright/rtsp/ARTPSession.cpp
@@ -82,7 +82,7 @@
         info->mRTPSocket = rtpSocket;
         info->mRTCPSocket = rtcpSocket;
 
-        sp<AMessage> notify = new AMessage(kWhatAccessUnitComplete, id());
+        sp<AMessage> notify = new AMessage(kWhatAccessUnitComplete, this);
         notify->setSize("track-index", mTracks.size() - 1);
 
         mRTPConn->addStream(
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 793d116..56c4aa6 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -146,7 +146,7 @@
         TRESPASS();
     }
 
-    (new AMessage(kWhatStart, mReflector->id()))->post();
+    (new AMessage(kWhatStart, mReflector))->post();
 
     while (!(mFlags & kFlagStarted)) {
         mCondition.wait(mLock);
@@ -161,7 +161,7 @@
         return OK;
     }
 
-    (new AMessage(kWhatStop, mReflector->id()))->post();
+    (new AMessage(kWhatStop, mReflector))->post();
 
     while (mFlags & kFlagStarted) {
         mCondition.wait(mLock);
@@ -213,8 +213,8 @@
                 mCondition.signal();
             }
 
-            (new AMessage(kWhatRead, mReflector->id()))->post();
-            (new AMessage(kWhatSendSR, mReflector->id()))->post();
+            (new AMessage(kWhatRead, mReflector))->post();
+            (new AMessage(kWhatSendSR, mReflector))->post();
             break;
         }
 
@@ -461,7 +461,7 @@
         sdp.append("m=audio ");
     }
 
-    sdp.append(StringPrintf("%d", ntohs(mRTPAddr.sin_port)));
+    sdp.append(AStringPrintf("%d", ntohs(mRTPAddr.sin_port)));
     sdp.append(
           " RTP/AVP " PT_STR "\r\n"
           "b=AS 320000\r\n"
@@ -480,7 +480,7 @@
         CHECK_EQ(sampleRate, (mMode == AMR_NB) ? 8000 : 16000);
 
         sdp.append(mMode == AMR_NB ? "AMR" : "AMR-WB");
-        sdp.append(StringPrintf("/%d/%d", sampleRate, numChannels));
+        sdp.append(AStringPrintf("/%d/%d", sampleRate, numChannels));
     } else {
         TRESPASS();
     }
@@ -543,7 +543,7 @@
     CHECK_EQ((unsigned)data[0], 0x67u);
 
     mProfileLevel =
-        StringPrintf("%02X%02X%02X", data[1], data[2], data[3]);
+        AStringPrintf("%02X%02X%02X", data[1], data[2], data[3]);
 
     encodeBase64(data, startCodePos, &mSeqParamSet);
 
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index f25539c..855ffdc 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -42,7 +42,7 @@
 
 // static
 const AString ARTSPConnection::sUserAgent =
-    StringPrintf("User-Agent: %s\r\n", MakeUserAgent().c_str());
+    AStringPrintf("User-Agent: %s\r\n", MakeUserAgent().c_str());
 
 ARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid)
     : mUIDValid(uidValid),
@@ -68,28 +68,28 @@
 }
 
 void ARTSPConnection::connect(const char *url, const sp<AMessage> &reply) {
-    sp<AMessage> msg = new AMessage(kWhatConnect, id());
+    sp<AMessage> msg = new AMessage(kWhatConnect, this);
     msg->setString("url", url);
     msg->setMessage("reply", reply);
     msg->post();
 }
 
 void ARTSPConnection::disconnect(const sp<AMessage> &reply) {
-    sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
+    sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
     msg->setMessage("reply", reply);
     msg->post();
 }
 
 void ARTSPConnection::sendRequest(
         const char *request, const sp<AMessage> &reply) {
-    sp<AMessage> msg = new AMessage(kWhatSendRequest, id());
+    sp<AMessage> msg = new AMessage(kWhatSendRequest, this);
     msg->setString("request", request);
     msg->setMessage("reply", reply);
     msg->post();
 }
 
 void ARTSPConnection::observeBinaryData(const sp<AMessage> &reply) {
-    sp<AMessage> msg = new AMessage(kWhatObserveBinaryData, id());
+    sp<AMessage> msg = new AMessage(kWhatObserveBinaryData, this);
     msg->setMessage("reply", reply);
     msg->post();
 }
@@ -286,7 +286,7 @@
 
     if (err < 0) {
         if (errno == EINPROGRESS) {
-            sp<AMessage> msg = new AMessage(kWhatCompleteConnection, id());
+            sp<AMessage> msg = new AMessage(kWhatCompleteConnection, this);
             msg->setMessage("reply", reply);
             msg->setInt32("connection-id", mConnectionID);
             msg->post();
@@ -523,7 +523,7 @@
         return;
     }
 
-    sp<AMessage> msg = new AMessage(kWhatReceiveResponse, id());
+    sp<AMessage> msg = new AMessage(kWhatReceiveResponse, this);
     msg->post();
 
     mReceiveResponseEventPending = true;
@@ -746,7 +746,7 @@
             AString request;
             CHECK(reply->findString("original-request", &request));
 
-            sp<AMessage> msg = new AMessage(kWhatSendRequest, id());
+            sp<AMessage> msg = new AMessage(kWhatSendRequest, this);
             msg->setMessage("reply", reply);
             msg->setString("request", request.c_str(), request.size());
 
diff --git a/media/libstagefright/rtsp/ARawAudioAssembler.h b/media/libstagefright/rtsp/ARawAudioAssembler.h
index ed7af08..bc1dea6 100644
--- a/media/libstagefright/rtsp/ARawAudioAssembler.h
+++ b/media/libstagefright/rtsp/ARawAudioAssembler.h
@@ -24,7 +24,7 @@
 
 struct AMessage;
 struct AString;
-struct MetaData;
+class MetaData;
 
 struct ARawAudioAssembler : public ARTPAssembler {
     ARawAudioAssembler(
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
index d60dc2f..9fedb71 100644
--- a/media/libstagefright/rtsp/Android.mk
+++ b/media/libstagefright/rtsp/Android.mk
@@ -19,10 +19,11 @@
         ASessionDescription.cpp     \
         SDPLoader.cpp               \
 
+LOCAL_SHARED_LIBRARIES += libcrypto
+
 LOCAL_C_INCLUDES:= \
 	$(TOP)/frameworks/av/media/libstagefright \
-	$(TOP)/frameworks/native/include/media/openmax \
-	$(TOP)/external/openssl/include
+	$(TOP)/frameworks/native/include/media/openmax
 
 LOCAL_MODULE:= libstagefright_rtsp
 
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 423a420..0642343 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -156,7 +156,7 @@
             mSessionURL.append("rtsp://");
             mSessionURL.append(host);
             mSessionURL.append(":");
-            mSessionURL.append(StringPrintf("%u", port));
+            mSessionURL.append(AStringPrintf("%u", port));
             mSessionURL.append(path);
 
             ALOGV("rewritten session url: '%s'", mSessionURL.c_str());
@@ -169,10 +169,10 @@
         looper()->registerHandler(mConn);
         (1 ? mNetLooper : looper())->registerHandler(mRTPConn);
 
-        sp<AMessage> notify = new AMessage('biny', id());
+        sp<AMessage> notify = new AMessage('biny', this);
         mConn->observeBinaryData(notify);
 
-        sp<AMessage> reply = new AMessage('conn', id());
+        sp<AMessage> reply = new AMessage('conn', this);
         mConn->connect(mOriginalSessionURL.c_str(), reply);
     }
 
@@ -180,10 +180,10 @@
         looper()->registerHandler(mConn);
         (1 ? mNetLooper : looper())->registerHandler(mRTPConn);
 
-        sp<AMessage> notify = new AMessage('biny', id());
+        sp<AMessage> notify = new AMessage('biny', this);
         mConn->observeBinaryData(notify);
 
-        sp<AMessage> reply = new AMessage('sdpl', id());
+        sp<AMessage> reply = new AMessage('sdpl', this);
         reply->setObject("description", desc);
         mConn->connect(mOriginalSessionURL.c_str(), reply);
     }
@@ -210,11 +210,11 @@
     }
 
     void disconnect() {
-        (new AMessage('abor', id()))->post();
+        (new AMessage('abor', this))->post();
     }
 
     void seek(int64_t timeUs) {
-        sp<AMessage> msg = new AMessage('seek', id());
+        sp<AMessage> msg = new AMessage('seek', this);
         msg->setInt64("time", timeUs);
         mPauseGeneration++;
         msg->post();
@@ -225,14 +225,14 @@
     }
 
     void pause() {
-        sp<AMessage> msg = new AMessage('paus', id());
+        sp<AMessage> msg = new AMessage('paus', this);
         mPauseGeneration++;
         msg->setInt32("pausecheck", mPauseGeneration);
         msg->post(kPauseDelayUs);
     }
 
     void resume() {
-        sp<AMessage> msg = new AMessage('resu', id());
+        sp<AMessage> msg = new AMessage('resu', this);
         mPauseGeneration++;
         msg->post();
     }
@@ -454,10 +454,10 @@
                     request.append("Accept: application/sdp\r\n");
                     request.append("\r\n");
 
-                    sp<AMessage> reply = new AMessage('desc', id());
+                    sp<AMessage> reply = new AMessage('desc', this);
                     mConn->sendRequest(request.c_str(), reply);
                 } else {
-                    (new AMessage('disc', id()))->post();
+                    (new AMessage('disc', this))->post();
                 }
                 break;
             }
@@ -468,10 +468,10 @@
 
                 int32_t reconnect;
                 if (msg->findInt32("reconnect", &reconnect) && reconnect) {
-                    sp<AMessage> reply = new AMessage('conn', id());
+                    sp<AMessage> reply = new AMessage('conn', this);
                     mConn->connect(mOriginalSessionURL.c_str(), reply);
                 } else {
-                    (new AMessage('quit', id()))->post();
+                    (new AMessage('quit', this))->post();
                 }
                 break;
             }
@@ -508,13 +508,13 @@
                             mSessionURL.append("rtsp://");
                             mSessionURL.append(host);
                             mSessionURL.append(":");
-                            mSessionURL.append(StringPrintf("%u", port));
+                            mSessionURL.append(AStringPrintf("%u", port));
                             mSessionURL.append(path);
 
                             ALOGI("rewritten session url: '%s'", mSessionURL.c_str());
                         }
 
-                        sp<AMessage> reply = new AMessage('conn', id());
+                        sp<AMessage> reply = new AMessage('conn', this);
                         mConn->connect(mOriginalSessionURL.c_str(), reply);
                         break;
                     }
@@ -586,7 +586,7 @@
                 }
 
                 if (result != OK) {
-                    sp<AMessage> reply = new AMessage('disc', id());
+                    sp<AMessage> reply = new AMessage('disc', this);
                     mConn->disconnect(reply);
                 }
                 break;
@@ -631,7 +631,7 @@
                 }
 
                 if (result != OK) {
-                    sp<AMessage> reply = new AMessage('disc', id());
+                    sp<AMessage> reply = new AMessage('disc', this);
                     mConn->disconnect(reply);
                 }
                 break;
@@ -703,7 +703,7 @@
                             mSessionID.erase(i, mSessionID.size() - i);
                         }
 
-                        sp<AMessage> notify = new AMessage('accu', id());
+                        sp<AMessage> notify = new AMessage('accu', this);
                         notify->setSize("track-index", trackIndex);
 
                         i = response->mHeaders.indexOfKey("transport");
@@ -769,10 +769,10 @@
 
                     request.append("\r\n");
 
-                    sp<AMessage> reply = new AMessage('play', id());
+                    sp<AMessage> reply = new AMessage('play', this);
                     mConn->sendRequest(request.c_str(), reply);
                 } else {
-                    sp<AMessage> reply = new AMessage('disc', id());
+                    sp<AMessage> reply = new AMessage('disc', this);
                     mConn->disconnect(reply);
                 }
                 break;
@@ -797,7 +797,7 @@
                     } else {
                         parsePlayResponse(response);
 
-                        sp<AMessage> timeout = new AMessage('tiou', id());
+                        sp<AMessage> timeout = new AMessage('tiou', this);
                         mCheckTimeoutGeneration++;
                         timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
                         timeout->post(kStartupTimeoutUs);
@@ -805,7 +805,7 @@
                 }
 
                 if (result != OK) {
-                    sp<AMessage> reply = new AMessage('disc', id());
+                    sp<AMessage> reply = new AMessage('disc', this);
                     mConn->disconnect(reply);
                 }
 
@@ -831,7 +831,7 @@
                 request.append("\r\n");
                 request.append("\r\n");
 
-                sp<AMessage> reply = new AMessage('opts', id());
+                sp<AMessage> reply = new AMessage('opts', this);
                 reply->setInt32("generation", mKeepAliveGeneration);
                 mConn->sendRequest(request.c_str(), reply);
                 break;
@@ -894,7 +894,7 @@
                 mPausing = false;
                 mSeekable = true;
 
-                sp<AMessage> reply = new AMessage('tear', id());
+                sp<AMessage> reply = new AMessage('tear', this);
 
                 int32_t reconnect;
                 if (msg->findInt32("reconnect", &reconnect) && reconnect) {
@@ -926,7 +926,7 @@
                 ALOGI("TEARDOWN completed with result %d (%s)",
                      result, strerror(-result));
 
-                sp<AMessage> reply = new AMessage('disc', id());
+                sp<AMessage> reply = new AMessage('disc', this);
 
                 int32_t reconnect;
                 if (msg->findInt32("reconnect", &reconnect) && reconnect) {
@@ -958,7 +958,7 @@
                 if (mNumAccessUnitsReceived == 0) {
 #if 1
                     ALOGI("stream ended? aborting.");
-                    (new AMessage('abor', id()))->post();
+                    (new AMessage('abor', this))->post();
                     break;
 #else
                     ALOGI("haven't seen an AU in a looong time.");
@@ -1077,7 +1077,7 @@
 
                 request.append("\r\n");
 
-                sp<AMessage> reply = new AMessage('pau2', id());
+                sp<AMessage> reply = new AMessage('pau2', this);
                 mConn->sendRequest(request.c_str(), reply);
                 break;
             }
@@ -1114,7 +1114,7 @@
 
                 request.append("\r\n");
 
-                sp<AMessage> reply = new AMessage('res2', id());
+                sp<AMessage> reply = new AMessage('res2', this);
                 mConn->sendRequest(request.c_str(), reply);
                 break;
             }
@@ -1143,7 +1143,7 @@
 
                         // Post new timeout in order to make sure to use
                         // fake timestamps if no new Sender Reports arrive
-                        sp<AMessage> timeout = new AMessage('tiou', id());
+                        sp<AMessage> timeout = new AMessage('tiou', this);
                         mCheckTimeoutGeneration++;
                         timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
                         timeout->post(kStartupTimeoutUs);
@@ -1152,7 +1152,7 @@
 
                 if (result != OK) {
                     ALOGE("resume failed, aborting.");
-                    (new AMessage('abor', id()))->post();
+                    (new AMessage('abor', this))->post();
                 }
 
                 mPausing = false;
@@ -1180,7 +1180,7 @@
                 mCheckPending = true;
                 ++mCheckGeneration;
 
-                sp<AMessage> reply = new AMessage('see1', id());
+                sp<AMessage> reply = new AMessage('see1', this);
                 reply->setInt64("time", timeUs);
 
                 if (mPausing) {
@@ -1221,7 +1221,7 @@
 
                 // Start new timeoutgeneration to avoid getting timeout
                 // before PLAY response arrive
-                sp<AMessage> timeout = new AMessage('tiou', id());
+                sp<AMessage> timeout = new AMessage('tiou', this);
                 mCheckTimeoutGeneration++;
                 timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
                 timeout->post(kStartupTimeoutUs);
@@ -1238,12 +1238,12 @@
                 request.append("\r\n");
 
                 request.append(
-                        StringPrintf(
+                        AStringPrintf(
                             "Range: npt=%lld-\r\n", timeUs / 1000000ll));
 
                 request.append("\r\n");
 
-                sp<AMessage> reply = new AMessage('see2', id());
+                sp<AMessage> reply = new AMessage('see2', this);
                 mConn->sendRequest(request.c_str(), reply);
                 break;
             }
@@ -1277,7 +1277,7 @@
 
                         // Post new timeout in order to make sure to use
                         // fake timestamps if no new Sender Reports arrive
-                        sp<AMessage> timeout = new AMessage('tiou', id());
+                        sp<AMessage> timeout = new AMessage('tiou', this);
                         mCheckTimeoutGeneration++;
                         timeout->setInt32("tioucheck", mCheckTimeoutGeneration);
                         timeout->post(kStartupTimeoutUs);
@@ -1293,7 +1293,7 @@
 
                 if (result != OK) {
                     ALOGE("seek failed, aborting.");
-                    (new AMessage('abor', id()))->post();
+                    (new AMessage('abor', this))->post();
                 }
 
                 mPausing = false;
@@ -1343,12 +1343,12 @@
 
                         mTryTCPInterleaving = true;
 
-                        sp<AMessage> msg = new AMessage('abor', id());
+                        sp<AMessage> msg = new AMessage('abor', this);
                         msg->setInt32("reconnect", true);
                         msg->post();
                     } else {
                         ALOGW("Never received any data, disconnecting.");
-                        (new AMessage('abor', id()))->post();
+                        (new AMessage('abor', this))->post();
                     }
                 } else {
                     if (!mAllTracksHaveTime) {
@@ -1369,7 +1369,7 @@
     }
 
     void postKeepAlive() {
-        sp<AMessage> msg = new AMessage('aliv', id());
+        sp<AMessage> msg = new AMessage('aliv', this);
         msg->setInt32("generation", mKeepAliveGeneration);
         msg->post((mKeepAliveTimeoutUs * 9) / 10);
     }
@@ -1380,7 +1380,7 @@
         }
 
         mCheckPending = true;
-        sp<AMessage> check = new AMessage('chek', id());
+        sp<AMessage> check = new AMessage('chek', this);
         check->setInt32("generation", mCheckGeneration);
         check->post(kAccessUnitTimeoutUs);
     }
@@ -1566,7 +1566,7 @@
         if (source->initCheck() != OK) {
             ALOGW("Unsupported format. Ignoring track #%d.", index);
 
-            sp<AMessage> reply = new AMessage('setu', id());
+            sp<AMessage> reply = new AMessage('setu', this);
             reply->setSize("index", index);
             reply->setInt32("result", ERROR_UNSUPPORTED);
             reply->post();
@@ -1652,7 +1652,7 @@
 
         request.append("\r\n");
 
-        sp<AMessage> reply = new AMessage('setu', id());
+        sp<AMessage> reply = new AMessage('setu', this);
         reply->setSize("index", index);
         reply->setSize("track-index", mTracks.size() - 1);
         mConn->sendRequest(request.c_str(), reply);
diff --git a/media/libstagefright/rtsp/MyTransmitter.h b/media/libstagefright/rtsp/MyTransmitter.h
index 009a3b1..369f276 100644
--- a/media/libstagefright/rtsp/MyTransmitter.h
+++ b/media/libstagefright/rtsp/MyTransmitter.h
@@ -100,7 +100,7 @@
         mLooper->registerHandler(this);
         mLooper->registerHandler(mConn);
 
-        sp<AMessage> reply = new AMessage('conn', id());
+        sp<AMessage> reply = new AMessage('conn', this);
         mConn->connect(mServerURL.c_str(), reply);
 
 #ifdef ANDROID
@@ -229,7 +229,7 @@
         request.append("\r\n");
         request.append(sdp);
 
-        sp<AMessage> reply = new AMessage('anno', id());
+        sp<AMessage> reply = new AMessage('anno', this);
         mConn->sendRequest(request.c_str(), reply);
     }
 
@@ -350,7 +350,7 @@
                      << result << " (" << strerror(-result) << ")";
 
                 if (result != OK) {
-                    (new AMessage('quit', id()))->post();
+                    (new AMessage('quit', this))->post();
                     break;
                 }
 
@@ -381,7 +381,7 @@
                     if (response->mStatusCode == 401) {
                         if (mAuthType != NONE) {
                             LOG(INFO) << "FAILED to authenticate";
-                            (new AMessage('quit', id()))->post();
+                            (new AMessage('quit', this))->post();
                             break;
                         }
 
@@ -391,14 +391,14 @@
                 }
 
                 if (result != OK || response->mStatusCode != 200) {
-                    (new AMessage('quit', id()))->post();
+                    (new AMessage('quit', this))->post();
                     break;
                 }
 
                 unsigned rtpPort;
                 ARTPConnection::MakePortPair(&mRTPSocket, &mRTCPSocket, &rtpPort);
 
-                // (new AMessage('poll', id()))->post();
+                // (new AMessage('poll', this))->post();
 
                 AString request;
                 request.append("SETUP ");
@@ -414,7 +414,7 @@
                 request.append(";mode=record\r\n");
                 request.append("\r\n");
 
-                sp<AMessage> reply = new AMessage('setu', id());
+                sp<AMessage> reply = new AMessage('setu', this);
                 mConn->sendRequest(request.c_str(), reply);
                 break;
             }
@@ -468,7 +468,7 @@
                 }
 
                 if (result != OK || response->mStatusCode != 200) {
-                    (new AMessage('quit', id()))->post();
+                    (new AMessage('quit', this))->post();
                     break;
                 }
 
@@ -535,7 +535,7 @@
                 request.append("\r\n");
                 request.append("\r\n");
 
-                sp<AMessage> reply = new AMessage('reco', id());
+                sp<AMessage> reply = new AMessage('reco', this);
                 mConn->sendRequest(request.c_str(), reply);
                 break;
             }
@@ -558,13 +558,13 @@
                 }
 
                 if (result != OK) {
-                    (new AMessage('quit', id()))->post();
+                    (new AMessage('quit', this))->post();
                     break;
                 }
 
-                (new AMessage('more', id()))->post();
-                (new AMessage('sr  ', id()))->post();
-                (new AMessage('aliv', id()))->post(30000000ll);
+                (new AMessage('more', this))->post();
+                (new AMessage('sr  ', this))->post();
+                (new AMessage('aliv', this))->post(30000000ll);
                 break;
             }
 
@@ -586,7 +586,7 @@
                 request.append("\r\n");
                 request.append("\r\n");
 
-                sp<AMessage> reply = new AMessage('opts', id());
+                sp<AMessage> reply = new AMessage('opts', this);
                 mConn->sendRequest(request.c_str(), reply);
                 break;
             }
@@ -603,7 +603,7 @@
                     break;
                 }
 
-                (new AMessage('aliv', id()))->post(30000000ll);
+                (new AMessage('aliv', this))->post(30000000ll);
                 break;
             }
 
@@ -702,7 +702,7 @@
                     request.append("\r\n");
                     request.append("\r\n");
 
-                    sp<AMessage> reply = new AMessage('paus', id());
+                    sp<AMessage> reply = new AMessage('paus', this);
                     mConn->sendRequest(request.c_str(), reply);
                 }
                 break;
@@ -753,7 +753,7 @@
                 request.append("\r\n");
                 request.append("\r\n");
 
-                sp<AMessage> reply = new AMessage('tear', id());
+                sp<AMessage> reply = new AMessage('tear', this);
                 mConn->sendRequest(request.c_str(), reply);
                 break;
             }
@@ -775,7 +775,7 @@
                     CHECK(response != NULL);
                 }
 
-                (new AMessage('quit', id()))->post();
+                (new AMessage('quit', this))->post();
                 break;
             }
 
@@ -784,14 +784,14 @@
                 LOG(INFO) << "disconnect completed";
 
                 mConnected = false;
-                (new AMessage('quit', id()))->post();
+                (new AMessage('quit', this))->post();
                 break;
             }
 
             case 'quit':
             {
                 if (mConnected) {
-                    mConn->disconnect(new AMessage('disc', id()));
+                    mConn->disconnect(new AMessage('disc', this));
                     break;
                 }
 
diff --git a/media/libstagefright/rtsp/SDPLoader.cpp b/media/libstagefright/rtsp/SDPLoader.cpp
index 424badf..0f46c83 100644
--- a/media/libstagefright/rtsp/SDPLoader.cpp
+++ b/media/libstagefright/rtsp/SDPLoader.cpp
@@ -51,7 +51,7 @@
 void SDPLoader::load(const char *url, const KeyedVector<String8, String8> *headers) {
     mNetLooper->registerHandler(this);
 
-    sp<AMessage> msg = new AMessage(kWhatLoad, id());
+    sp<AMessage> msg = new AMessage(kWhatLoad, this);
     msg->setString("url", url);
 
     if (headers != NULL) {
@@ -105,7 +105,7 @@
         headers = NULL;
     }
 
-    off64_t sdpSize;
+    off64_t sdpSize = 0;
     if (err == OK && !mCancelled) {
         err = mHTTPDataSource->getSize(&sdpSize);
 
diff --git a/media/libstagefright/rtsp/UDPPusher.cpp b/media/libstagefright/rtsp/UDPPusher.cpp
index 47ea6f1..5c685a1 100644
--- a/media/libstagefright/rtsp/UDPPusher.cpp
+++ b/media/libstagefright/rtsp/UDPPusher.cpp
@@ -65,7 +65,7 @@
     mFirstTimeMs = fromlel(timeMs);
     mFirstTimeUs = ALooper::GetNowUs();
 
-    (new AMessage(kWhatPush, id()))->post();
+    (new AMessage(kWhatPush, this))->post();
 }
 
 bool UDPPusher::onPush() {
@@ -103,7 +103,7 @@
     timeMs -= mFirstTimeMs;
     int64_t whenUs = mFirstTimeUs + timeMs * 1000ll;
     int64_t nowUs = ALooper::GetNowUs();
-    (new AMessage(kWhatPush, id()))->post(whenUs - nowUs);
+    (new AMessage(kWhatPush, this))->post(whenUs - nowUs);
 
     return true;
 }
diff --git a/media/libstagefright/tests/Utils_test.cpp b/media/libstagefright/tests/Utils_test.cpp
index f2825dd..5c323c1 100644
--- a/media/libstagefright/tests/Utils_test.cpp
+++ b/media/libstagefright/tests/Utils_test.cpp
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AStringUtils.h>
 #include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/Utils.h>
 
@@ -32,6 +33,100 @@
 class UtilsTest : public ::testing::Test {
 };
 
+TEST_F(UtilsTest, TestStringUtils) {
+    ASSERT_EQ(AStringUtils::Compare("Audio", "AudioExt", 5, false), 0);
+    ASSERT_EQ(AStringUtils::Compare("Audio", "audiOExt", 5, true), 0);
+    ASSERT_NE(AStringUtils::Compare("Audio", "audioExt", 5, false), 0);
+    ASSERT_NE(AStringUtils::Compare("Audio", "AudiOExt", 5, false), 0);
+
+    ASSERT_LT(AStringUtils::Compare("Audio", "AudioExt", 7, false), 0);
+    ASSERT_LT(AStringUtils::Compare("Audio", "audiOExt", 7, true), 0);
+
+    ASSERT_GT(AStringUtils::Compare("AudioExt", "Audio", 7, false), 0);
+    ASSERT_GT(AStringUtils::Compare("audiOext", "Audio", 7, true), 0);
+
+    ASSERT_LT(AStringUtils::Compare("Audio", "Video", 5, false), 0);
+    ASSERT_LT(AStringUtils::Compare("Audio1", "Audio2", 6, false), 0);
+    ASSERT_LT(AStringUtils::Compare("audio", "VIDEO", 5, true), 0);
+    ASSERT_LT(AStringUtils::Compare("audio1", "AUDIO2", 6, true), 0);
+
+    ASSERT_GT(AStringUtils::Compare("Video", "Audio", 5, false), 0);
+    ASSERT_GT(AStringUtils::Compare("Audio2", "Audio1", 6, false), 0);
+    ASSERT_GT(AStringUtils::Compare("VIDEO", "audio", 5, true), 0);
+    ASSERT_GT(AStringUtils::Compare("AUDIO2", "audio1", 6, true), 0);
+
+    ASSERT_TRUE(AStringUtils::MatchesGlob("AudioA", 5, "AudioB", 5, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("AudioA", 6, "AudioA", 5, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("AudioA", 5, "AudioA", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("AudioA", 5, "audiOB", 5, false));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("AudioA", 5, "audiOB", 5, true));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("AudioA", 6, "AudioA", 5, true));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("AudioA", 5, "AudioA", 6, true));
+
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*1", 1, "String8", 6, true));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*1", 1, "String8", 6, false));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*1", 1, "String8", 0, true));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*1", 1, "String8", 0, false));
+
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*ring1", 5, "String8", 6, false));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*ring2", 5, "STRING8", 6, true));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("*ring4", 5, "StRing8", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("*ring5", 5, "StrinG8", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("*ring8", 5, "String8", 7, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("*ring8", 5, "String8", 7, true));
+
+    ASSERT_TRUE(AStringUtils::MatchesGlob("Str*1", 4, "String8", 6, false));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("Str*2", 4, "STRING8", 6, true));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*3", 4, "string8", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*4", 4, "StRing8", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*5", 4, "AString8", 7, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*6", 4, "AString8", 7, true));
+
+    ASSERT_TRUE(AStringUtils::MatchesGlob("Str*ng1", 6, "String8", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng2", 6, "string8", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng3", 6, "StRing8", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng4", 6, "StriNg8", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng5", 6, "StrinG8", 6, false));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("Str*ng6", 6, "STRING8", 6, true));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng8", 6, "AString8", 7, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng1", 6, "String16", 7, false));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("Str*ing9", 7, "String8", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ringA", 8, "String8", 6, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng8", 6, "AString8", 7, true));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng1", 6, "String16", 7, true));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("Str*ing9", 7, "STRING8", 6, true));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ringA", 8, "String8", 6, true));
+
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str1", 8, "bestrestroom", 9, false));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str1", 8, "bestrestrestroom", 13, false));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("*str*stro", 8, "bestrestrestroom", 14, false));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str*1", 9, "bestrestrestroom", 14, false));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str1", 8, "beSTReSTRoom", 9, true));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str1", 8, "beSTRestreSTRoom", 13, true));
+    ASSERT_FALSE(AStringUtils::MatchesGlob("*str*stro", 8, "bestreSTReSTRoom", 14, true));
+    ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str*1", 9, "bestreSTReSTRoom", 14, true));
+}
+
+TEST_F(UtilsTest, TestDebug) {
+#define LVL(x) (ADebug::Level)(x)
+    ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "", LVL(5)), LVL(5));
+    ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "   \t  \n ", LVL(2)), LVL(2));
+    ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "3", LVL(5)), LVL(3));
+    ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "3:*deo", LVL(5)), LVL(3));
+    ASSERT_EQ(ADebug::GetDebugLevelFromString(
+            "video", "\t\n 3 \t\n:\t\n video \t\n", LVL(5)), LVL(3));
+    ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "3:*deo,2:vid*", LVL(5)), LVL(2));
+    ASSERT_EQ(ADebug::GetDebugLevelFromString(
+            "avideo", "\t\n 3 \t\n:\t\n avideo \t\n,\t\n 2 \t\n:\t\n video \t\n", LVL(5)), LVL(3));
+    ASSERT_EQ(ADebug::GetDebugLevelFromString(
+            "audio.omx", "4:*omx,3:*d*o*,2:audio*", LVL(5)), LVL(2));
+    ASSERT_EQ(ADebug::GetDebugLevelFromString(
+            "video.omx", "4:*omx,3:*d*o*,2:audio*", LVL(5)), LVL(3));
+    ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "4:*omx,3:*d*o*,2:audio*", LVL(5)), LVL(3));
+    ASSERT_EQ(ADebug::GetDebugLevelFromString("omx", "4:*omx,3:*d*o*,2:audio*", LVL(5)), LVL(4));
+#undef LVL
+}
+
 TEST_F(UtilsTest, TestFourCC) {
     ASSERT_EQ(FOURCC('s', 't', 'm' , 'u'), 'stmu');
 }
@@ -77,6 +172,13 @@
     ASSERT_EQ(divUp(12, 4), 3);
     ASSERT_EQ(divUp(13, 4), 4);
 
+    ASSERT_EQ(align(11, 4), 12);
+    ASSERT_EQ(align(12, 4), 12);
+    ASSERT_EQ(align(13, 4), 16);
+    ASSERT_EQ(align(11, 8), 16);
+    ASSERT_EQ(align(11, 2), 12);
+    ASSERT_EQ(align(11, 1), 11);
+
     ASSERT_EQ(abs(5L), 5L);
     ASSERT_EQ(abs(-25), 25);
 
diff --git a/media/libstagefright/timedtext/TimedTextDriver.cpp b/media/libstagefright/timedtext/TimedTextDriver.cpp
index 71aa21e..55a9803 100644
--- a/media/libstagefright/timedtext/TimedTextDriver.cpp
+++ b/media/libstagefright/timedtext/TimedTextDriver.cpp
@@ -133,7 +133,7 @@
             }
             mPlayer->start();
             break;
-        defaut:
+        default:
             TRESPASS();
     }
     return ret;
@@ -181,7 +181,7 @@
         case PLAYING:
             mPlayer->seekToAsync(timeUs);
             return OK;
-        defaut:
+        default:
             TRESPASS();
     }
     return UNKNOWN_ERROR;
diff --git a/media/libstagefright/timedtext/TimedTextPlayer.cpp b/media/libstagefright/timedtext/TimedTextPlayer.cpp
index a070487..aecf666 100644
--- a/media/libstagefright/timedtext/TimedTextPlayer.cpp
+++ b/media/libstagefright/timedtext/TimedTextPlayer.cpp
@@ -56,25 +56,25 @@
 }
 
 void TimedTextPlayer::start() {
-    (new AMessage(kWhatStart, id()))->post();
+    (new AMessage(kWhatStart, this))->post();
 }
 
 void TimedTextPlayer::pause() {
-    (new AMessage(kWhatPause, id()))->post();
+    (new AMessage(kWhatPause, this))->post();
 }
 
 void TimedTextPlayer::resume() {
-    (new AMessage(kWhatResume, id()))->post();
+    (new AMessage(kWhatResume, this))->post();
 }
 
 void TimedTextPlayer::seekToAsync(int64_t timeUs) {
-    sp<AMessage> msg = new AMessage(kWhatSeek, id());
+    sp<AMessage> msg = new AMessage(kWhatSeek, this);
     msg->setInt64("seekTimeUs", timeUs);
     msg->post();
 }
 
 void TimedTextPlayer::setDataSource(sp<TimedTextSource> source) {
-    sp<AMessage> msg = new AMessage(kWhatSetSource, id());
+    sp<AMessage> msg = new AMessage(kWhatSetSource, this);
     msg->setObject("source", source);
     msg->post();
 }
@@ -231,7 +231,7 @@
     status_t err = mSource->read(&startTimeUs, &endTimeUs,
                                  &(parcelEvent->parcel), options);
     if (err == WOULD_BLOCK) {
-        sp<AMessage> msg = new AMessage(kWhatRetryRead, id());
+        sp<AMessage> msg = new AMessage(kWhatRetryRead, this);
         if (options != NULL) {
             int64_t seekTimeUs = kInvalidTimeUs;
             MediaSource::ReadOptions::SeekMode seekMode =
@@ -259,7 +259,7 @@
 
 void TimedTextPlayer::postTextEvent(const sp<ParcelEvent>& parcel, int64_t timeUs) {
     int64_t delayUs = delayUsFromCurrentTime(timeUs);
-    sp<AMessage> msg = new AMessage(kWhatSendSubtitle, id());
+    sp<AMessage> msg = new AMessage(kWhatSendSubtitle, this);
     msg->setInt32("generation", mSendSubtitleGeneration);
     if (parcel != NULL) {
         msg->setObject("subtitle", parcel);
diff --git a/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp b/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp
index 40e93c7..3a06d61 100644
--- a/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp
+++ b/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp
@@ -120,26 +120,26 @@
         err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
         EXPECT_EQ(OK, err);
         CheckStartTimeMs(parcel, i * kSecToMsec);
-        subtitle = StringPrintf("%d\n\n", i);
+        subtitle = AStringPrintf("%d\n\n", i);
         CheckDataEquals(parcel, subtitle.c_str());
     }
     // read edge cases
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
     EXPECT_EQ(OK, err);
     CheckStartTimeMs(parcel, 5500);
-    subtitle = StringPrintf("6\n\n");
+    subtitle = AStringPrintf("6\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
     EXPECT_EQ(OK, err);
     CheckStartTimeMs(parcel, 5800);
-    subtitle = StringPrintf("7\n\n");
+    subtitle = AStringPrintf("7\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
     EXPECT_EQ(OK, err);
     CheckStartTimeMs(parcel, 6000);
-    subtitle = StringPrintf("8\n\n");
+    subtitle = AStringPrintf("8\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
@@ -202,21 +202,21 @@
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
     EXPECT_EQ(OK, err);
     EXPECT_EQ(5500 * kMsecToUsec, startTimeUs);
-    subtitle = StringPrintf("6\n\n");
+    subtitle = AStringPrintf("6\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 
     options.setSeekTo(5800 * kMsecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
     EXPECT_EQ(OK, err);
     EXPECT_EQ(5800 * kMsecToUsec, startTimeUs);
-    subtitle = StringPrintf("7\n\n");
+    subtitle = AStringPrintf("7\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 
     options.setSeekTo(6000 * kMsecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
     EXPECT_EQ(OK, err);
     EXPECT_EQ(6000 * kMsecToUsec, startTimeUs);
-    subtitle = StringPrintf("8\n\n");
+    subtitle = AStringPrintf("8\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 }
 
diff --git a/media/libstagefright/webm/WebmWriter.cpp b/media/libstagefright/webm/WebmWriter.cpp
index 03cf92a..737f144 100644
--- a/media/libstagefright/webm/WebmWriter.cpp
+++ b/media/libstagefright/webm/WebmWriter.cpp
@@ -80,38 +80,6 @@
             mCuePoints);
 }
 
-WebmWriter::WebmWriter(const char *filename)
-    : mInitCheck(NO_INIT),
-      mTimeCodeScale(1000000),
-      mStartTimestampUs(0),
-      mStartTimeOffsetMs(0),
-      mSegmentOffset(0),
-      mSegmentDataStart(0),
-      mInfoOffset(0),
-      mInfoSize(0),
-      mTracksOffset(0),
-      mCuesOffset(0),
-      mPaused(false),
-      mStarted(false),
-      mIsFileSizeLimitExplicitlyRequested(false),
-      mIsRealTimeRecording(false),
-      mStreamableFile(true),
-      mEstimatedCuesSize(0) {
-    mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
-    if (mFd >= 0) {
-        ALOGV("fd %d; flags: %o", mFd, fcntl(mFd, F_GETFL, 0));
-        mInitCheck = OK;
-    }
-    mStreams[kAudioIndex] = WebmStream(kAudioType, "Audio", &WebmWriter::audioTrack);
-    mStreams[kVideoIndex] = WebmStream(kVideoType, "Video", &WebmWriter::videoTrack);
-    mSinkThread = new WebmFrameSinkThread(
-            mFd,
-            mSegmentDataStart,
-            mStreams[kVideoIndex].mSink,
-            mStreams[kAudioIndex].mSink,
-            mCuePoints);
-}
-
 // static
 sp<WebmElement> WebmWriter::videoTrack(const sp<MetaData>& md) {
     int32_t width, height;
@@ -333,7 +301,6 @@
     serializeCodedUnsigned(segmentSizeCoded, bary);
     ::write(mFd, bary, sizeOf(kMkvUnknownLength));
 
-    uint64_t size;
     uint64_t durationOffset = mInfoOffset + sizeOf(kMkvInfo) + sizeOf(mInfoSize)
         + sizeOf(kMkvSegmentDuration) + sizeOf(sizeof(double));
     sp<WebmElement> duration = new WebmFloat(
diff --git a/media/libstagefright/webm/WebmWriter.h b/media/libstagefright/webm/WebmWriter.h
index 36b6965..4ad770e 100644
--- a/media/libstagefright/webm/WebmWriter.h
+++ b/media/libstagefright/webm/WebmWriter.h
@@ -37,7 +37,6 @@
 class WebmWriter : public MediaWriter {
 public:
     WebmWriter(int fd);
-    WebmWriter(const char *filename);
     ~WebmWriter() { reset(); }
 
 
diff --git a/media/libstagefright/wifi-display/MediaSender.cpp b/media/libstagefright/wifi-display/MediaSender.cpp
index b1cdec0..6f0087f 100644
--- a/media/libstagefright/wifi-display/MediaSender.cpp
+++ b/media/libstagefright/wifi-display/MediaSender.cpp
@@ -121,7 +121,7 @@
         }
 
         if (err == OK) {
-            sp<AMessage> notify = new AMessage(kWhatSenderNotify, id());
+            sp<AMessage> notify = new AMessage(kWhatSenderNotify, this);
             notify->setInt32("generation", mGeneration);
             mTSSender = new RTPSender(mNetSession, notify);
             looper()->registerHandler(mTSSender);
@@ -170,7 +170,7 @@
         return INVALID_OPERATION;
     }
 
-    sp<AMessage> notify = new AMessage(kWhatSenderNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatSenderNotify, this);
     notify->setInt32("generation", mGeneration);
     notify->setSize("trackIndex", trackIndex);
 
diff --git a/media/libstagefright/wifi-display/VideoFormats.cpp b/media/libstagefright/wifi-display/VideoFormats.cpp
index 04e02c1..2f4af5b 100644
--- a/media/libstagefright/wifi-display/VideoFormats.cpp
+++ b/media/libstagefright/wifi-display/VideoFormats.cpp
@@ -435,7 +435,7 @@
     //   max-hres (none or 2 byte)
     //   max-vres (none or 2 byte)
 
-    return StringPrintf(
+    return AStringPrintf(
             "%02x 00 %02x %02x %08x %08x %08x 00 0000 0000 00 none none",
             forM4Message ? 0x00 : ((mNativeIndex << 3) | mNativeType),
             mConfigs[mNativeType][mNativeIndex].profile,
diff --git a/media/libstagefright/wifi-display/rtp/RTPSender.cpp b/media/libstagefright/wifi-display/rtp/RTPSender.cpp
index e88a3bd..4e72533 100644
--- a/media/libstagefright/wifi-display/rtp/RTPSender.cpp
+++ b/media/libstagefright/wifi-display/rtp/RTPSender.cpp
@@ -95,11 +95,11 @@
         return INVALID_OPERATION;
     }
 
-    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
+    sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, this);
 
     sp<AMessage> rtcpNotify;
     if (remoteRTCPPort >= 0) {
-        rtcpNotify = new AMessage(kWhatRTCPNotify, id());
+        rtcpNotify = new AMessage(kWhatRTCPNotify, this);
     }
 
     CHECK_EQ(mRTPSessionID, 0);
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index 2834a66..8368945 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -93,7 +93,7 @@
 
 void Converter::shutdownAsync() {
     ALOGV("shutdown");
-    (new AMessage(kWhatShutdown, id()))->post();
+    (new AMessage(kWhatShutdown, this))->post();
 }
 
 status_t Converter::init() {
@@ -482,11 +482,11 @@
 
 #if 1
     if (mEncoderActivityNotify == NULL) {
-        mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, id());
+        mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, this);
     }
     mEncoder->requestActivityNotification(mEncoderActivityNotify->dup());
 #else
-    sp<AMessage> notify = new AMessage(kWhatEncoderActivity, id());
+    sp<AMessage> notify = new AMessage(kWhatEncoderActivity, this);
     notify->setInt64("whenUs", ALooper::GetNowUs());
     mEncoder->requestActivityNotification(notify);
 #endif
@@ -731,8 +731,7 @@
 
                 // MediaSender will post the following message when HDCP
                 // is done, to release the output buffer back to encoder.
-                sp<AMessage> notify(new AMessage(
-                        kWhatReleaseOutputBuffer, id()));
+                sp<AMessage> notify(new AMessage(kWhatReleaseOutputBuffer, this));
                 notify->setInt32("bufferIndex", bufferIndex);
 
                 buffer = new ABuffer(
@@ -787,18 +786,18 @@
 }
 
 void Converter::requestIDRFrame() {
-    (new AMessage(kWhatRequestIDRFrame, id()))->post();
+    (new AMessage(kWhatRequestIDRFrame, this))->post();
 }
 
 void Converter::dropAFrame() {
     // Unsupported in surface input mode.
     CHECK(!(mFlags & FLAG_USE_SURFACE_INPUT));
 
-    (new AMessage(kWhatDropAFrame, id()))->post();
+    (new AMessage(kWhatDropAFrame, this))->post();
 }
 
 void Converter::suspendEncoding(bool suspend) {
-    sp<AMessage> msg = new AMessage(kWhatSuspendEncoding, id());
+    sp<AMessage> msg = new AMessage(kWhatSuspendEncoding, this);
     msg->setInt32("suspend", suspend);
     msg->post();
 }
diff --git a/media/libstagefright/wifi-display/source/MediaPuller.cpp b/media/libstagefright/wifi-display/source/MediaPuller.cpp
index 86b918f..ce07a4e 100644
--- a/media/libstagefright/wifi-display/source/MediaPuller.cpp
+++ b/media/libstagefright/wifi-display/source/MediaPuller.cpp
@@ -63,21 +63,21 @@
 }
 
 status_t MediaPuller::start() {
-    return postSynchronouslyAndReturnError(new AMessage(kWhatStart, id()));
+    return postSynchronouslyAndReturnError(new AMessage(kWhatStart, this));
 }
 
 void MediaPuller::stopAsync(const sp<AMessage> &notify) {
-    sp<AMessage> msg = new AMessage(kWhatStop, id());
+    sp<AMessage> msg = new AMessage(kWhatStop, this);
     msg->setMessage("notify", notify);
     msg->post();
 }
 
 void MediaPuller::pause() {
-    (new AMessage(kWhatPause, id()))->post();
+    (new AMessage(kWhatPause, this))->post();
 }
 
 void MediaPuller::resume() {
-    (new AMessage(kWhatResume, id()))->post();
+    (new AMessage(kWhatResume, this))->post();
 }
 
 void MediaPuller::onMessageReceived(const sp<AMessage> &msg) {
@@ -105,7 +105,7 @@
             sp<AMessage> response = new AMessage;
             response->setInt32("err", err);
 
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
             response->postReply(replyID);
             break;
@@ -215,7 +215,7 @@
 }
 
 void MediaPuller::schedulePull() {
-    sp<AMessage> msg = new AMessage(kWhatPull, id());
+    sp<AMessage> msg = new AMessage(kWhatPull, this);
     msg->setInt32("generation", mPullGeneration);
     msg->post();
 }
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index 2cb4786..6080943 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -214,7 +214,7 @@
         mConverter->shutdownAsync();
     }
 
-    sp<AMessage> msg = new AMessage(kWhatMediaPullerStopped, id());
+    sp<AMessage> msg = new AMessage(kWhatMediaPullerStopped, this);
 
     if (mStarted && mMediaPuller != NULL) {
         if (mRepeaterSource != NULL) {
@@ -382,7 +382,7 @@
         size_t videoResolutionIndex,
         VideoFormats::ProfileType videoProfileType,
         VideoFormats::LevelType videoLevelType) {
-    sp<AMessage> notify = new AMessage(kWhatMediaSenderNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatMediaSenderNotify, this);
     mMediaSender = new MediaSender(mNetSession, notify);
     looper()->registerHandler(mMediaSender);
 
@@ -440,7 +440,7 @@
 status_t WifiDisplaySource::PlaybackSession::play() {
     updateLiveness();
 
-    (new AMessage(kWhatResume, id()))->post();
+    (new AMessage(kWhatResume, this))->post();
 
     return OK;
 }
@@ -460,7 +460,7 @@
 status_t WifiDisplaySource::PlaybackSession::pause() {
     updateLiveness();
 
-    (new AMessage(kWhatPause, id()))->post();
+    (new AMessage(kWhatPause, this))->post();
 
     return OK;
 }
@@ -786,7 +786,7 @@
 
         size_t trackIndex = mTracks.size();
 
-        sp<AMessage> notify = new AMessage(kWhatTrackNotify, id());
+        sp<AMessage> notify = new AMessage(kWhatTrackNotify, this);
         notify->setSize("trackIndex", trackIndex);
 
         sp<Track> track = new Track(notify, format);
@@ -833,7 +833,7 @@
 
     int64_t whenUs = sampleTimeUs - mFirstSampleTimeUs + mFirstSampleTimeRealUs;
 
-    sp<AMessage> msg = new AMessage(kWhatPullExtractorSample, id());
+    sp<AMessage> msg = new AMessage(kWhatPullExtractorSample, this);
     msg->setInt32("generation", mPullExtractorGeneration);
     msg->post(whenUs - nowUs);
 
@@ -857,7 +857,7 @@
     size_t trackIndex;
     CHECK_EQ((status_t)OK, mExtractor->getSampleTrackIndex(&trackIndex));
 
-    sp<AMessage> msg = new AMessage(kWhatConverterNotify, id());
+    sp<AMessage> msg = new AMessage(kWhatConverterNotify, this);
 
     msg->setSize(
             "trackIndex", mExtractorTrackToInternalTrack.valueFor(trackIndex));
@@ -955,7 +955,7 @@
                     ? MEDIA_MIMETYPE_AUDIO_RAW : MEDIA_MIMETYPE_AUDIO_AAC);
     }
 
-    notify = new AMessage(kWhatConverterNotify, id());
+    notify = new AMessage(kWhatConverterNotify, this);
     notify->setSize("trackIndex", trackIndex);
 
     sp<Converter> converter = new Converter(notify, codecLooper, format);
@@ -970,7 +970,7 @@
         return err;
     }
 
-    notify = new AMessage(Converter::kWhatMediaPullerNotify, converter->id());
+    notify = new AMessage(Converter::kWhatMediaPullerNotify, converter);
     notify->setSize("trackIndex", trackIndex);
 
     sp<MediaPuller> puller = new MediaPuller(source, notify);
@@ -980,7 +980,7 @@
         *numInputBuffers = converter->getInputBufferCount();
     }
 
-    notify = new AMessage(kWhatTrackNotify, id());
+    notify = new AMessage(kWhatTrackNotify, this);
     notify->setSize("trackIndex", trackIndex);
 
     sp<Track> track = new Track(
diff --git a/media/libstagefright/wifi-display/source/RepeaterSource.cpp b/media/libstagefright/wifi-display/source/RepeaterSource.cpp
index 59d7e6e..af6b663 100644
--- a/media/libstagefright/wifi-display/source/RepeaterSource.cpp
+++ b/media/libstagefright/wifi-display/source/RepeaterSource.cpp
@@ -173,7 +173,7 @@
 }
 
 void RepeaterSource::postRead() {
-    (new AMessage(kWhatRead, mReflector->id()))->post();
+    (new AMessage(kWhatRead, mReflector))->post();
 }
 
 void RepeaterSource::onMessageReceived(const sp<AMessage> &msg) {
diff --git a/media/libstagefright/wifi-display/source/TSPacketizer.cpp b/media/libstagefright/wifi-display/source/TSPacketizer.cpp
index 50d317a..4c5ad17 100644
--- a/media/libstagefright/wifi-display/source/TSPacketizer.cpp
+++ b/media/libstagefright/wifi-display/source/TSPacketizer.cpp
@@ -106,7 +106,7 @@
             || !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
         for (size_t i = 0;; ++i) {
             sp<ABuffer> csd;
-            if (!mFormat->findBuffer(StringPrintf("csd-%d", i).c_str(), &csd)) {
+            if (!mFormat->findBuffer(AStringPrintf("csd-%d", i).c_str(), &csd)) {
                 break;
             }
 
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 0c39ccf..14d0951 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -57,7 +57,7 @@
       mNetSession(netSession),
       mClient(client),
       mSessionID(0),
-      mStopReplyID(0),
+      mStopReplyID(NULL),
       mChosenRTPPort(-1),
       mUsingPCMAudio(false),
       mClientSessionID(0),
@@ -106,7 +106,7 @@
 status_t WifiDisplaySource::start(const char *iface) {
     CHECK_EQ(mState, INITIALIZED);
 
-    sp<AMessage> msg = new AMessage(kWhatStart, id());
+    sp<AMessage> msg = new AMessage(kWhatStart, this);
     msg->setString("iface", iface);
 
     sp<AMessage> response;
@@ -114,21 +114,21 @@
 }
 
 status_t WifiDisplaySource::stop() {
-    sp<AMessage> msg = new AMessage(kWhatStop, id());
+    sp<AMessage> msg = new AMessage(kWhatStop, this);
 
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
 
 status_t WifiDisplaySource::pause() {
-    sp<AMessage> msg = new AMessage(kWhatPause, id());
+    sp<AMessage> msg = new AMessage(kWhatPause, this);
 
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
 
 status_t WifiDisplaySource::resume() {
-    sp<AMessage> msg = new AMessage(kWhatResume, id());
+    sp<AMessage> msg = new AMessage(kWhatResume, this);
 
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
@@ -138,7 +138,7 @@
     switch (msg->what()) {
         case kWhatStart:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             AString iface;
@@ -167,7 +167,7 @@
 
             if (err == OK) {
                 if (inet_aton(iface.c_str(), &mInterfaceAddr) != 0) {
-                    sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id());
+                    sp<AMessage> notify = new AMessage(kWhatRTSPNotify, this);
 
                     err = mNetSession->createRTSPServer(
                             mInterfaceAddr, port, notify, &mSessionID);
@@ -310,7 +310,7 @@
                 if (err == OK) {
                     mState = AWAITING_CLIENT_TEARDOWN;
 
-                    (new AMessage(kWhatTeardownTriggerTimedOut, id()))->post(
+                    (new AMessage(kWhatTeardownTriggerTimedOut, this))->post(
                             kTeardownTriggerTimeouSecs * 1000000ll);
 
                     break;
@@ -325,7 +325,7 @@
 
         case kWhatPause:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             status_t err = OK;
@@ -345,7 +345,7 @@
 
         case kWhatResume:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             CHECK(msg->senderAwaitsResponse(&replyID));
 
             status_t err = OK;
@@ -492,7 +492,7 @@
             if (mState == AWAITING_CLIENT_TEARDOWN) {
                 ALOGI("TEARDOWN trigger timed out, forcing disconnection.");
 
-                CHECK_NE(mStopReplyID, 0);
+                CHECK(mStopReplyID != NULL);
                 finishStop();
                 break;
             }
@@ -529,7 +529,7 @@
                     // HDCPObserver::notify is completely handled before
                     // we clear the HDCP instance and unload the shared
                     // library :(
-                    (new AMessage(kWhatFinishStop2, id()))->post(300000ll);
+                    (new AMessage(kWhatFinishStop2, this))->post(300000ll);
                     break;
                 }
 
@@ -598,7 +598,7 @@
     AppendCommonResponse(&request, mNextCSeq);
 
     request.append("Content-Type: text/parameters\r\n");
-    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
+    request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
     request.append("\r\n");
     request.append(body);
 
@@ -639,26 +639,26 @@
 
     if (mSinkSupportsAudio) {
         body.append(
-                StringPrintf("wfd_audio_codecs: %s\r\n",
+                AStringPrintf("wfd_audio_codecs: %s\r\n",
                              (mUsingPCMAudio
                                 ? "LPCM 00000002 00" // 2 ch PCM 48kHz
                                 : "AAC 00000001 00")));  // 2 ch AAC 48kHz
     }
 
     body.append(
-            StringPrintf(
+            AStringPrintf(
                 "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n",
                 mClientInfo.mLocalIP.c_str()));
 
     body.append(
-            StringPrintf(
+            AStringPrintf(
                 "wfd_client_rtp_ports: %s\r\n", mWfdClientRtpPorts.c_str()));
 
     AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
     AppendCommonResponse(&request, mNextCSeq);
 
     request.append("Content-Type: text/parameters\r\n");
-    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
+    request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
     request.append("\r\n");
     request.append(body);
 
@@ -704,7 +704,7 @@
     AppendCommonResponse(&request, mNextCSeq);
 
     request.append("Content-Type: text/parameters\r\n");
-    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
+    request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
     request.append("\r\n");
     request.append(body);
 
@@ -729,7 +729,7 @@
 
     CHECK_EQ(sessionID, mClientSessionID);
     request.append(
-            StringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
+            AStringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
     request.append("\r\n");  // Empty body
 
     status_t err =
@@ -1027,7 +1027,7 @@
     }
 
     mReaperPending = true;
-    (new AMessage(kWhatReapDeadClients, id()))->post(kReaperIntervalUs);
+    (new AMessage(kWhatReapDeadClients, this))->post(kReaperIntervalUs);
 }
 
 void WifiDisplaySource::scheduleKeepAlive(int32_t sessionID) {
@@ -1035,7 +1035,7 @@
     // expire, make sure the timeout is greater than 5 secs to begin with.
     CHECK_GT(kPlaybackSessionTimeoutUs, 5000000ll);
 
-    sp<AMessage> msg = new AMessage(kWhatKeepAlive, id());
+    sp<AMessage> msg = new AMessage(kWhatKeepAlive, this);
     msg->setInt32("sessionID", sessionID);
     msg->post(kPlaybackSessionTimeoutUs - 5000000ll);
 }
@@ -1239,7 +1239,7 @@
 
     int32_t playbackSessionID = makeUniquePlaybackSessionID();
 
-    sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, this);
     notify->setInt32("playbackSessionID", playbackSessionID);
     notify->setInt32("sessionID", sessionID);
 
@@ -1305,7 +1305,7 @@
 
     if (rtpMode == RTPSender::TRANSPORT_TCP_INTERLEAVED) {
         response.append(
-                StringPrintf(
+                AStringPrintf(
                     "Transport: RTP/AVP/TCP;interleaved=%d-%d;",
                     clientRtp, clientRtcp));
     } else {
@@ -1318,14 +1318,14 @@
 
         if (clientRtcp >= 0) {
             response.append(
-                    StringPrintf(
+                    AStringPrintf(
                         "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;"
                         "server_port=%d-%d\r\n",
                         transportString.c_str(),
                         clientRtp, clientRtcp, serverRtp, serverRtp + 1));
         } else {
             response.append(
-                    StringPrintf(
+                    AStringPrintf(
                         "Transport: RTP/AVP/%s;unicast;client_port=%d;"
                         "server_port=%d\r\n",
                         transportString.c_str(),
@@ -1470,7 +1470,7 @@
     mNetSession->sendRequest(sessionID, response.c_str());
 
     if (mState == AWAITING_CLIENT_TEARDOWN) {
-        CHECK_NE(mStopReplyID, 0);
+        CHECK(mStopReplyID != NULL);
         finishStop();
     } else {
         mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown);
@@ -1585,15 +1585,15 @@
     response->append(buf);
     response->append("\r\n");
 
-    response->append(StringPrintf("Server: %s\r\n", sUserAgent.c_str()));
+    response->append(AStringPrintf("Server: %s\r\n", sUserAgent.c_str()));
 
     if (cseq >= 0) {
-        response->append(StringPrintf("CSeq: %d\r\n", cseq));
+        response->append(AStringPrintf("CSeq: %d\r\n", cseq));
     }
 
     if (playbackSessionID >= 0ll) {
         response->append(
-                StringPrintf(
+                AStringPrintf(
                     "Session: %d;timeout=%lld\r\n",
                     playbackSessionID, kPlaybackSessionTimeoutSecs));
     }
@@ -1707,7 +1707,7 @@
         return ERROR_UNSUPPORTED;
     }
 
-    sp<AMessage> notify = new AMessage(kWhatHDCPNotify, id());
+    sp<AMessage> notify = new AMessage(kWhatHDCPNotify, this);
     mHDCPObserver = new HDCPObserver(notify);
 
     status_t err = mHDCP->setObserver(mHDCPObserver);
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index 750265f..0f779e4 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -27,6 +27,7 @@
 
 namespace android {
 
+struct AReplyToken;
 struct IHDCP;
 struct IRemoteDisplayClient;
 struct ParsedMessage;
@@ -121,7 +122,7 @@
     struct in_addr mInterfaceAddr;
     int32_t mSessionID;
 
-    uint32_t mStopReplyID;
+    sp<AReplyToken> mStopReplyID;
 
     AString mWfdClientRtpPorts;
     int32_t mChosenRTPPort;  // extracted from "wfd_client_rtp_ports"
diff --git a/media/libstagefright/yuv/YUVImage.cpp b/media/libstagefright/yuv/YUVImage.cpp
index bb3e2fd..c098135 100644
--- a/media/libstagefright/yuv/YUVImage.cpp
+++ b/media/libstagefright/yuv/YUVImage.cpp
@@ -374,13 +374,13 @@
 
 void YUVImage::yuv2rgb(uint8_t yValue, uint8_t uValue, uint8_t vValue,
         uint8_t *r, uint8_t *g, uint8_t *b) const {
-    *r = yValue + (1.370705 * (vValue-128));
-    *g = yValue - (0.698001 * (vValue-128)) - (0.337633 * (uValue-128));
-    *b = yValue + (1.732446 * (uValue-128));
+    int rTmp = yValue + (1.370705 * (vValue-128));
+    int gTmp = yValue - (0.698001 * (vValue-128)) - (0.337633 * (uValue-128));
+    int bTmp = yValue + (1.732446 * (uValue-128));
 
-    *r = clamp(*r, 0, 255);
-    *g = clamp(*g, 0, 255);
-    *b = clamp(*b, 0, 255);
+    *r = clamp(rTmp, 0, 255);
+    *g = clamp(gTmp, 0, 255);
+    *b = clamp(bTmp, 0, 255);
 }
 
 bool YUVImage::writeToPPM(const char *filename) const {
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index 3a280f0..0ad0bf3 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -11,7 +11,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	main_mediaserver.cpp 
+	main_mediaserver.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libaudioflinger \
@@ -26,7 +26,8 @@
 	libutils \
 	liblog \
 	libbinder \
-	libsoundtriggerservice
+	libsoundtriggerservice \
+	libradioservice
 
 LOCAL_STATIC_LIBRARIES := \
 	libregistermsext
@@ -38,7 +39,8 @@
     frameworks/av/services/audiopolicy \
     frameworks/av/services/camera/libcameraservice \
     $(call include-path-for, audio-utils) \
-    frameworks/av/services/soundtrigger
+    frameworks/av/services/soundtrigger \
+    frameworks/av/services/radio
 
 LOCAL_MODULE:= mediaserver
 LOCAL_32_BIT_ONLY := true
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index af1c9e6..99572f8 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -33,8 +33,9 @@
 #include "CameraService.h"
 #include "MediaLogService.h"
 #include "MediaPlayerService.h"
-#include "AudioPolicyService.h"
+#include "service/AudioPolicyService.h"
 #include "SoundTriggerHwService.h"
+#include "RadioService.h"
 
 using namespace android;
 
@@ -130,6 +131,7 @@
         CameraService::instantiate();
         AudioPolicyService::instantiate();
         SoundTriggerHwService::instantiate();
+        RadioService::instantiate();
         registerExtensions();
         ProcessState::self()->startThreadPool();
         IPCThreadState::self()->joinThreadPool();
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index e6e19e3..052b700 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -51,104 +51,178 @@
     MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
 }
 
-uint16_t MtpDataPacket::getUInt16() {
-    int offset = mOffset;
-    uint16_t result = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);
-    mOffset += 2;
-    return result;
+bool MtpDataPacket::getUInt8(uint8_t& value) {
+    if (mPacketSize - mOffset < sizeof(value))
+        return false;
+    value = mBuffer[mOffset++];
+    return true;
 }
 
-uint32_t MtpDataPacket::getUInt32() {
+bool MtpDataPacket::getUInt16(uint16_t& value) {
+    if (mPacketSize - mOffset < sizeof(value))
+        return false;
     int offset = mOffset;
-    uint32_t result = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |
+    value = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);
+    mOffset += sizeof(value);
+    return true;
+}
+
+bool MtpDataPacket::getUInt32(uint32_t& value) {
+    if (mPacketSize - mOffset < sizeof(value))
+        return false;
+    int offset = mOffset;
+    value = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |
            ((uint32_t)mBuffer[offset + 2] << 16)  | ((uint32_t)mBuffer[offset + 3] << 24);
-    mOffset += 4;
-    return result;
+    mOffset += sizeof(value);
+    return true;
 }
 
-uint64_t MtpDataPacket::getUInt64() {
+bool MtpDataPacket::getUInt64(uint64_t& value) {
+    if (mPacketSize - mOffset < sizeof(value))
+        return false;
     int offset = mOffset;
-    uint64_t result = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |
+    value = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |
            ((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) |
            ((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) |
            ((uint64_t)mBuffer[offset + 6] << 48)  | ((uint64_t)mBuffer[offset + 7] << 56);
-    mOffset += 8;
-    return result;
+    mOffset += sizeof(value);
+    return true;
 }
 
-void MtpDataPacket::getUInt128(uint128_t& value) {
-    value[0] = getUInt32();
-    value[1] = getUInt32();
-    value[2] = getUInt32();
-    value[3] = getUInt32();
+bool MtpDataPacket::getUInt128(uint128_t& value) {
+    return getUInt32(value[0]) && getUInt32(value[1]) && getUInt32(value[2]) && getUInt32(value[3]);
 }
 
-void MtpDataPacket::getString(MtpStringBuffer& string)
+bool MtpDataPacket::getString(MtpStringBuffer& string)
 {
-    string.readFromPacket(this);
+    return string.readFromPacket(this);
 }
 
 Int8List* MtpDataPacket::getAInt8() {
+    uint32_t count;
+    if (!getUInt32(count))
+        return NULL;
     Int8List* result = new Int8List;
-    int count = getUInt32();
-    for (int i = 0; i < count; i++)
-        result->push(getInt8());
+    for (uint32_t i = 0; i < count; i++) {
+        int8_t value;
+        if (!getInt8(value)) {
+            delete result;
+            return NULL;
+        }
+        result->push(value);
+    }
     return result;
 }
 
 UInt8List* MtpDataPacket::getAUInt8() {
+    uint32_t count;
+    if (!getUInt32(count))
+        return NULL;
     UInt8List* result = new UInt8List;
-    int count = getUInt32();
-    for (int i = 0; i < count; i++)
-        result->push(getUInt8());
+    for (uint32_t i = 0; i < count; i++) {
+        uint8_t value;
+        if (!getUInt8(value)) {
+            delete result;
+            return NULL;
+        }
+        result->push(value);
+    }
     return result;
 }
 
 Int16List* MtpDataPacket::getAInt16() {
+    uint32_t count;
+    if (!getUInt32(count))
+        return NULL;
     Int16List* result = new Int16List;
-    int count = getUInt32();
-    for (int i = 0; i < count; i++)
-        result->push(getInt16());
+    for (uint32_t i = 0; i < count; i++) {
+        int16_t value;
+        if (!getInt16(value)) {
+            delete result;
+            return NULL;
+        }
+        result->push(value);
+    }
     return result;
 }
 
 UInt16List* MtpDataPacket::getAUInt16() {
+    uint32_t count;
+    if (!getUInt32(count))
+        return NULL;
     UInt16List* result = new UInt16List;
-    int count = getUInt32();
-    for (int i = 0; i < count; i++)
-        result->push(getUInt16());
+    for (uint32_t i = 0; i < count; i++) {
+        uint16_t value;
+        if (!getUInt16(value)) {
+            delete result;
+            return NULL;
+        }
+        result->push(value);
+    }
     return result;
 }
 
 Int32List* MtpDataPacket::getAInt32() {
+    uint32_t count;
+    if (!getUInt32(count))
+        return NULL;
     Int32List* result = new Int32List;
-    int count = getUInt32();
-    for (int i = 0; i < count; i++)
-        result->push(getInt32());
+    for (uint32_t i = 0; i < count; i++) {
+        int32_t value;
+        if (!getInt32(value)) {
+            delete result;
+            return NULL;
+        }
+        result->push(value);
+    }
     return result;
 }
 
 UInt32List* MtpDataPacket::getAUInt32() {
+    uint32_t count;
+    if (!getUInt32(count))
+        return NULL;
     UInt32List* result = new UInt32List;
-    int count = getUInt32();
-    for (int i = 0; i < count; i++)
-        result->push(getUInt32());
+    for (uint32_t i = 0; i < count; i++) {
+        uint32_t value;
+        if (!getUInt32(value)) {
+            delete result;
+            return NULL;
+        }
+        result->push(value);
+    }
     return result;
 }
 
 Int64List* MtpDataPacket::getAInt64() {
+    uint32_t count;
+    if (!getUInt32(count))
+        return NULL;
     Int64List* result = new Int64List;
-    int count = getUInt32();
-    for (int i = 0; i < count; i++)
-        result->push(getInt64());
+    for (uint32_t i = 0; i < count; i++) {
+        int64_t value;
+        if (!getInt64(value)) {
+            delete result;
+            return NULL;
+        }
+        result->push(value);
+    }
     return result;
 }
 
 UInt64List* MtpDataPacket::getAUInt64() {
+    uint32_t count;
+    if (!getUInt32(count))
+        return NULL;
     UInt64List* result = new UInt64List;
-    int count = getUInt32();
-    for (int i = 0; i < count; i++)
-        result->push(getUInt64());
+    for (uint32_t i = 0; i < count; i++) {
+        uint64_t value;
+        if (!getUInt64(value)) {
+            delete result;
+            return NULL;
+        }
+        result->push(value);
+    }
     return result;
 }
 
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 2b81063..13d3bd9 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -30,7 +30,7 @@
 class MtpDataPacket : public MtpPacket {
 private:
     // current offset for get/put methods
-    int                 mOffset;
+    size_t              mOffset;
 
 public:
                         MtpDataPacket();
@@ -42,17 +42,18 @@
     void                setTransactionID(MtpTransactionID id);
 
     inline const uint8_t*     getData() const { return mBuffer + MTP_CONTAINER_HEADER_SIZE; }
-    inline uint8_t      getUInt8() { return (uint8_t)mBuffer[mOffset++]; }
-    inline int8_t       getInt8() { return (int8_t)mBuffer[mOffset++]; }
-    uint16_t            getUInt16();
-    inline int16_t      getInt16() { return (int16_t)getUInt16(); }
-    uint32_t            getUInt32();
-    inline int32_t      getInt32() { return (int32_t)getUInt32(); }
-    uint64_t            getUInt64();
-    inline int64_t      getInt64() { return (int64_t)getUInt64(); }
-    void                getUInt128(uint128_t& value);
-    inline void         getInt128(int128_t& value) { getUInt128((uint128_t&)value); }
-    void                getString(MtpStringBuffer& string);
+
+    bool                getUInt8(uint8_t& value);
+    inline bool         getInt8(int8_t& value) { return getUInt8((uint8_t&)value); }
+    bool                getUInt16(uint16_t& value);
+    inline bool         getInt16(int16_t& value) { return getUInt16((uint16_t&)value); }
+    bool                getUInt32(uint32_t& value);
+    inline bool         getInt32(int32_t& value) { return getUInt32((uint32_t&)value); }
+    bool                getUInt64(uint64_t& value);
+    inline bool         getInt64(int64_t& value) { return getUInt64((uint64_t&)value); }
+    bool                getUInt128(uint128_t& value);
+    inline bool         getInt128(int128_t& value) { return getUInt128((uint128_t&)value); }
+    bool                getString(MtpStringBuffer& string);
 
     Int8List*           getAInt8();
     UInt8List*          getAUInt8();
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 96331b5..3eafd6f 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -322,8 +322,10 @@
     MtpResponseCode ret = readResponse();
     if (ret == MTP_RESPONSE_OK) {
         MtpDeviceInfo* info = new MtpDeviceInfo;
-        info->read(mData);
-        return info;
+        if (info->read(mData))
+            return info;
+        else
+            delete info;
     }
     return NULL;
 }
@@ -355,8 +357,10 @@
     MtpResponseCode ret = readResponse();
     if (ret == MTP_RESPONSE_OK) {
         MtpStorageInfo* info = new MtpStorageInfo(storageID);
-        info->read(mData);
-        return info;
+        if (info->read(mData))
+            return info;
+        else
+            delete info;
     }
     return NULL;
 }
@@ -394,8 +398,10 @@
     MtpResponseCode ret = readResponse();
     if (ret == MTP_RESPONSE_OK) {
         MtpObjectInfo* info = new MtpObjectInfo(handle);
-        info->read(mData);
-        return info;
+        if (info->read(mData))
+            return info;
+        else
+            delete info;
     }
     return NULL;
 }
@@ -556,8 +562,10 @@
     MtpResponseCode ret = readResponse();
     if (ret == MTP_RESPONSE_OK) {
         MtpProperty* property = new MtpProperty;
-        property->read(mData);
-        return property;
+        if (property->read(mData))
+            return property;
+        else
+            delete property;
     }
     return NULL;
 }
@@ -575,15 +583,17 @@
     MtpResponseCode ret = readResponse();
     if (ret == MTP_RESPONSE_OK) {
         MtpProperty* property = new MtpProperty;
-        property->read(mData);
-        return property;
+        if (property->read(mData))
+            return property;
+        else
+            delete property;
     }
     return NULL;
 }
 
 bool MtpDevice::readObject(MtpObjectHandle handle,
         bool (* callback)(void* data, int offset, int length, void* clientData),
-        int objectSize, void* clientData) {
+        size_t objectSize, void* clientData) {
     Mutex::Autolock autoLock(mMutex);
     bool result = false;
 
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index b69203e..9b0acbf 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -98,7 +98,7 @@
     bool                    readObject(MtpObjectHandle handle,
                                     bool (* callback)(void* data, int offset,
                                             int length, void* clientData),
-                                    int objectSize, void* clientData);
+                                    size_t objectSize, void* clientData);
     bool                    readObject(MtpObjectHandle handle, const char* destPath, int group,
                                     int perm);
 
diff --git a/media/mtp/MtpDeviceInfo.cpp b/media/mtp/MtpDeviceInfo.cpp
index 108e2b8..3e1dff7 100644
--- a/media/mtp/MtpDeviceInfo.cpp
+++ b/media/mtp/MtpDeviceInfo.cpp
@@ -28,7 +28,7 @@
         mVendorExtensionID(0),
         mVendorExtensionVersion(0),
         mVendorExtensionDesc(NULL),
-        mFunctionalCode(0),
+        mFunctionalMode(0),
         mOperations(NULL),
         mEvents(NULL),
         mDeviceProperties(NULL),
@@ -59,39 +59,46 @@
         free(mSerial);
 }
 
-void MtpDeviceInfo::read(MtpDataPacket& packet) {
+bool MtpDeviceInfo::read(MtpDataPacket& packet) {
     MtpStringBuffer string;
 
     // read the device info
-    mStandardVersion = packet.getUInt16();
-    mVendorExtensionID = packet.getUInt32();
-    mVendorExtensionVersion = packet.getUInt16();
+    if (!packet.getUInt16(mStandardVersion)) return false;
+    if (!packet.getUInt32(mVendorExtensionID)) return false;
+    if (!packet.getUInt16(mVendorExtensionVersion)) return false;
 
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     mVendorExtensionDesc = strdup((const char *)string);
 
-    mFunctionalCode = packet.getUInt16();
+    if (!packet.getUInt16(mFunctionalMode)) return false;
     mOperations = packet.getAUInt16();
+    if (!mOperations) return false;
     mEvents = packet.getAUInt16();
+    if (!mEvents) return false;
     mDeviceProperties = packet.getAUInt16();
+    if (!mDeviceProperties) return false;
     mCaptureFormats = packet.getAUInt16();
+    if (!mCaptureFormats) return false;
     mPlaybackFormats = packet.getAUInt16();
+    if (!mCaptureFormats) return false;
 
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     mManufacturer = strdup((const char *)string);
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     mModel = strdup((const char *)string);
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     mVersion = strdup((const char *)string);
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     mSerial = strdup((const char *)string);
+
+    return true;
 }
 
 void MtpDeviceInfo::print() {
     ALOGV("Device Info:\n\tmStandardVersion: %d\n\tmVendorExtensionID: %d\n\tmVendorExtensionVersiony: %d\n",
             mStandardVersion, mVendorExtensionID, mVendorExtensionVersion);
-    ALOGV("\tmVendorExtensionDesc: %s\n\tmFunctionalCode: %d\n\tmManufacturer: %s\n\tmModel: %s\n\tmVersion: %s\n\tmSerial: %s\n",
-            mVendorExtensionDesc, mFunctionalCode, mManufacturer, mModel, mVersion, mSerial);
+    ALOGV("\tmVendorExtensionDesc: %s\n\tmFunctionalMode: %d\n\tmManufacturer: %s\n\tmModel: %s\n\tmVersion: %s\n\tmSerial: %s\n",
+            mVendorExtensionDesc, mFunctionalMode, mManufacturer, mModel, mVersion, mSerial);
 }
 
 }  // namespace android
diff --git a/media/mtp/MtpDeviceInfo.h b/media/mtp/MtpDeviceInfo.h
index 2abaa10..bcda9a5 100644
--- a/media/mtp/MtpDeviceInfo.h
+++ b/media/mtp/MtpDeviceInfo.h
@@ -29,7 +29,7 @@
     uint32_t                mVendorExtensionID;
     uint16_t                mVendorExtensionVersion;
     char*                   mVendorExtensionDesc;
-    uint16_t                mFunctionalCode;
+    uint16_t                mFunctionalMode;
     UInt16List*             mOperations;
     UInt16List*             mEvents;
     MtpDevicePropertyList*  mDeviceProperties;
@@ -44,7 +44,7 @@
                             MtpDeviceInfo();
     virtual                 ~MtpDeviceInfo();
 
-    void                    read(MtpDataPacket& packet);
+    bool                    read(MtpDataPacket& packet);
 
     void                    print();
 };
diff --git a/media/mtp/MtpObjectInfo.cpp b/media/mtp/MtpObjectInfo.cpp
index cd15343..0573104 100644
--- a/media/mtp/MtpObjectInfo.cpp
+++ b/media/mtp/MtpObjectInfo.cpp
@@ -55,39 +55,41 @@
         free(mKeywords);
 }
 
-void MtpObjectInfo::read(MtpDataPacket& packet) {
+bool MtpObjectInfo::read(MtpDataPacket& packet) {
     MtpStringBuffer string;
     time_t time;
 
-    mStorageID = packet.getUInt32();
-    mFormat = packet.getUInt16();
-    mProtectionStatus = packet.getUInt16();
-    mCompressedSize = packet.getUInt32();
-    mThumbFormat = packet.getUInt16();
-    mThumbCompressedSize = packet.getUInt32();
-    mThumbPixWidth = packet.getUInt32();
-    mThumbPixHeight = packet.getUInt32();
-    mImagePixWidth = packet.getUInt32();
-    mImagePixHeight = packet.getUInt32();
-    mImagePixDepth = packet.getUInt32();
-    mParent = packet.getUInt32();
-    mAssociationType = packet.getUInt16();
-    mAssociationDesc = packet.getUInt32();
-    mSequenceNumber = packet.getUInt32();
+    if (!packet.getUInt32(mStorageID)) return false;
+    if (!packet.getUInt16(mFormat)) return false;
+    if (!packet.getUInt16(mProtectionStatus)) return false;
+    if (!packet.getUInt32(mCompressedSize)) return false;
+    if (!packet.getUInt16(mThumbFormat)) return false;
+    if (!packet.getUInt32(mThumbCompressedSize)) return false;
+    if (!packet.getUInt32(mThumbPixWidth)) return false;
+    if (!packet.getUInt32(mThumbPixHeight)) return false;
+    if (!packet.getUInt32(mImagePixWidth)) return false;
+    if (!packet.getUInt32(mImagePixHeight)) return false;
+    if (!packet.getUInt32(mImagePixDepth)) return false;
+    if (!packet.getUInt32(mParent)) return false;
+    if (!packet.getUInt16(mAssociationType)) return false;
+    if (!packet.getUInt32(mAssociationDesc)) return false;
+    if (!packet.getUInt32(mSequenceNumber)) return false;
 
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     mName = strdup((const char *)string);
 
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     if (parseDateTime((const char*)string, time))
         mDateCreated = time;
 
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     if (parseDateTime((const char*)string, time))
         mDateModified = time;
 
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     mKeywords = strdup((const char *)string);
+
+    return true;
 }
 
 void MtpObjectInfo::print() {
diff --git a/media/mtp/MtpObjectInfo.h b/media/mtp/MtpObjectInfo.h
index c7a449c..86780f1 100644
--- a/media/mtp/MtpObjectInfo.h
+++ b/media/mtp/MtpObjectInfo.h
@@ -50,7 +50,7 @@
                         MtpObjectInfo(MtpObjectHandle handle);
     virtual             ~MtpObjectInfo();
 
-    void                read(MtpDataPacket& packet);
+    bool                read(MtpDataPacket& packet);
 
     void                print();
 };
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index dd07843..bab1335 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -52,7 +52,7 @@
     memset(mBuffer, 0, mBufferSize);
 }
 
-void MtpPacket::allocate(int length) {
+void MtpPacket::allocate(size_t length) {
     if (length > mBufferSize) {
         int newLength = length + mAllocationIncrement;
         mBuffer = (uint8_t *)realloc(mBuffer, newLength);
diff --git a/media/mtp/MtpPacket.h b/media/mtp/MtpPacket.h
index 0ffb1d3..037722a 100644
--- a/media/mtp/MtpPacket.h
+++ b/media/mtp/MtpPacket.h
@@ -28,11 +28,11 @@
 protected:
     uint8_t*            mBuffer;
     // current size of the buffer
-    int                 mBufferSize;
+    size_t              mBufferSize;
     // number of bytes to add when resizing the buffer
-    int                 mAllocationIncrement;
+    size_t              mAllocationIncrement;
     // size of the data in the packet
-    int                 mPacketSize;
+    size_t              mPacketSize;
 
 public:
                         MtpPacket(int bufferSize);
@@ -41,7 +41,7 @@
     // sets packet size to the default container size and sets buffer to zero
     virtual void        reset();
 
-    void                allocate(int length);
+    void                allocate(size_t length);
     void                dump();
     void                copyFrom(const MtpPacket& src);
 
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
index c500901..d58e2a4 100644
--- a/media/mtp/MtpProperty.cpp
+++ b/media/mtp/MtpProperty.cpp
@@ -106,15 +106,15 @@
         free(mMinimumValue.str);
         free(mMaximumValue.str);
         if (mDefaultArrayValues) {
-            for (int i = 0; i < mDefaultArrayLength; i++)
+            for (uint32_t i = 0; i < mDefaultArrayLength; i++)
                 free(mDefaultArrayValues[i].str);
         }
         if (mCurrentArrayValues) {
-            for (int i = 0; i < mCurrentArrayLength; i++)
+            for (uint32_t i = 0; i < mCurrentArrayLength; i++)
                 free(mCurrentArrayValues[i].str);
         }
         if (mEnumValues) {
-            for (int i = 0; i < mEnumLength; i++)
+            for (uint16_t i = 0; i < mEnumLength; i++)
                 free(mEnumValues[i].str);
         }
     }
@@ -123,11 +123,14 @@
     delete[] mEnumValues;
 }
 
-void MtpProperty::read(MtpDataPacket& packet) {
-    mCode = packet.getUInt16();
+bool MtpProperty::read(MtpDataPacket& packet) {
+    uint8_t temp8;
+
+    if (!packet.getUInt16(mCode)) return false;
     bool deviceProp = isDeviceProperty();
-    mType = packet.getUInt16();
-    mWriteable = (packet.getUInt8() == 1);
+    if (!packet.getUInt16(mType)) return false;
+    if (!packet.getUInt8(temp8)) return false;
+    mWriteable = (temp8 == 1);
     switch (mType) {
         case MTP_TYPE_AINT8:
         case MTP_TYPE_AUINT8:
@@ -140,28 +143,36 @@
         case MTP_TYPE_AINT128:
         case MTP_TYPE_AUINT128:
             mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);
-            if (deviceProp)
+            if (!mDefaultArrayValues) return false;
+            if (deviceProp) {
                 mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
+                if (!mCurrentArrayValues) return false;
+            }
             break;
         default:
-            readValue(packet, mDefaultValue);
-            if (deviceProp)
-                readValue(packet, mCurrentValue);
+            if (!readValue(packet, mDefaultValue)) return false;
+            if (deviceProp) {
+                if (!readValue(packet, mCurrentValue)) return false;
+            }
     }
-    if (!deviceProp)
-        mGroupCode = packet.getUInt32();
-    mFormFlag = packet.getUInt8();
+    if (!deviceProp) {
+        if (!packet.getUInt32(mGroupCode)) return false;
+    }
+    if (!packet.getUInt8(mFormFlag)) return false;
 
     if (mFormFlag == kFormRange) {
-            readValue(packet, mMinimumValue);
-            readValue(packet, mMaximumValue);
-            readValue(packet, mStepSize);
+            if (!readValue(packet, mMinimumValue)) return false;
+            if (!readValue(packet, mMaximumValue)) return false;
+            if (!readValue(packet, mStepSize)) return false;
     } else if (mFormFlag == kFormEnum) {
-        mEnumLength = packet.getUInt16();
+        if (!packet.getUInt16(mEnumLength)) return false;
         mEnumValues = new MtpPropertyValue[mEnumLength];
-        for (int i = 0; i < mEnumLength; i++)
-            readValue(packet, mEnumValues[i]);
+        for (int i = 0; i < mEnumLength; i++) {
+            if (!readValue(packet, mEnumValues[i])) return false;
+        }
     }
+
+    return true;
 }
 
 void MtpProperty::write(MtpDataPacket& packet) {
@@ -409,57 +420,59 @@
     }
 }
 
-void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
+bool MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
     MtpStringBuffer stringBuffer;
 
     switch (mType) {
         case MTP_TYPE_INT8:
         case MTP_TYPE_AINT8:
-            value.u.i8 = packet.getInt8();
+            if (!packet.getInt8(value.u.i8)) return false;
             break;
         case MTP_TYPE_UINT8:
         case MTP_TYPE_AUINT8:
-            value.u.u8 = packet.getUInt8();
+            if (!packet.getUInt8(value.u.u8)) return false;
             break;
         case MTP_TYPE_INT16:
         case MTP_TYPE_AINT16:
-            value.u.i16 = packet.getInt16();
+            if (!packet.getInt16(value.u.i16)) return false;
             break;
         case MTP_TYPE_UINT16:
         case MTP_TYPE_AUINT16:
-            value.u.u16 = packet.getUInt16();
+            if (!packet.getUInt16(value.u.u16)) return false;
             break;
         case MTP_TYPE_INT32:
         case MTP_TYPE_AINT32:
-            value.u.i32 = packet.getInt32();
+            if (!packet.getInt32(value.u.i32)) return false;
             break;
         case MTP_TYPE_UINT32:
         case MTP_TYPE_AUINT32:
-            value.u.u32 = packet.getUInt32();
+            if (!packet.getUInt32(value.u.u32)) return false;
             break;
         case MTP_TYPE_INT64:
         case MTP_TYPE_AINT64:
-            value.u.i64 = packet.getInt64();
+            if (!packet.getInt64(value.u.i64)) return false;
             break;
         case MTP_TYPE_UINT64:
         case MTP_TYPE_AUINT64:
-            value.u.u64 = packet.getUInt64();
+            if (!packet.getUInt64(value.u.u64)) return false;
             break;
         case MTP_TYPE_INT128:
         case MTP_TYPE_AINT128:
-            packet.getInt128(value.u.i128);
+            if (!packet.getInt128(value.u.i128)) return false;
             break;
         case MTP_TYPE_UINT128:
         case MTP_TYPE_AUINT128:
-            packet.getUInt128(value.u.u128);
+            if (!packet.getUInt128(value.u.u128)) return false;
             break;
         case MTP_TYPE_STR:
-            packet.getString(stringBuffer);
+            if (!packet.getString(stringBuffer)) return false;
             value.str = strdup(stringBuffer);
             break;
         default:
             ALOGE("unknown type %04X in MtpProperty::readValue", mType);
+            return false;
     }
+    return true;
 }
 
 void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
@@ -517,8 +530,9 @@
     }
 }
 
-MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) {
-    length = packet.getUInt32();
+MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, uint32_t& length) {
+    if (!packet.getUInt32(length)) return NULL;
+
     // Fail if resulting array is over 2GB.  This is because the maximum array
     // size may be less than SIZE_MAX on some platforms.
     if ( CC_UNLIKELY(
@@ -528,14 +542,17 @@
         return NULL;
     }
     MtpPropertyValue* result = new MtpPropertyValue[length];
-    for (int i = 0; i < length; i++)
-        readValue(packet, result[i]);
+    for (uint32_t i = 0; i < length; i++)
+        if (!readValue(packet, result[i])) {
+            delete result;
+            return NULL;
+        }
     return result;
 }
 
-void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length) {
+void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, uint32_t length) {
     packet.putUInt32(length);
-    for (int i = 0; i < length; i++)
+    for (uint32_t i = 0; i < length; i++)
         writeValue(packet, values[i]);
 }
 
diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h
index 06ca56e..2e2ead1 100644
--- a/media/mtp/MtpProperty.h
+++ b/media/mtp/MtpProperty.h
@@ -49,9 +49,9 @@
     MtpPropertyValue    mCurrentValue;
 
     // for array types
-    int                 mDefaultArrayLength;
+    uint32_t            mDefaultArrayLength;
     MtpPropertyValue*   mDefaultArrayValues;
-    int                 mCurrentArrayLength;
+    uint32_t            mCurrentArrayLength;
     MtpPropertyValue*   mCurrentArrayValues;
 
     enum {
@@ -70,7 +70,7 @@
     MtpPropertyValue    mStepSize;
 
     // for enum form
-    int                 mEnumLength;
+    uint16_t            mEnumLength;
     MtpPropertyValue*   mEnumValues;
 
 public:
@@ -83,7 +83,7 @@
 
     inline MtpPropertyCode getPropertyCode() const { return mCode; }
 
-    void                read(MtpDataPacket& packet);
+    bool                read(MtpDataPacket& packet);
     void                write(MtpDataPacket& packet);
 
     void                setDefaultValue(const uint16_t* string);
@@ -102,11 +102,11 @@
                         }
 
 private:
-    void                readValue(MtpDataPacket& packet, MtpPropertyValue& value);
+    bool                readValue(MtpDataPacket& packet, MtpPropertyValue& value);
     void                writeValue(MtpDataPacket& packet, MtpPropertyValue& value);
-    MtpPropertyValue*   readArrayValues(MtpDataPacket& packet, int& length);
+    MtpPropertyValue*   readArrayValues(MtpDataPacket& packet, uint32_t& length);
     void                writeArrayValues(MtpDataPacket& packet,
-                                            MtpPropertyValue* values, int length);
+                                            MtpPropertyValue* values, uint32_t length);
 };
 
 }; // namespace android
diff --git a/media/mtp/MtpRequestPacket.cpp b/media/mtp/MtpRequestPacket.cpp
index 0e58e01..40b11b0 100644
--- a/media/mtp/MtpRequestPacket.cpp
+++ b/media/mtp/MtpRequestPacket.cpp
@@ -27,7 +27,8 @@
 namespace android {
 
 MtpRequestPacket::MtpRequestPacket()
-    :   MtpPacket(512)
+    :   MtpPacket(512),
+        mParameterCount(0)
 {
 }
 
@@ -37,10 +38,21 @@
 #ifdef MTP_DEVICE
 int MtpRequestPacket::read(int fd) {
     int ret = ::read(fd, mBuffer, mBufferSize);
-    if (ret >= 0)
+    if (ret < 0) {
+        // file read error
+        return ret;
+    }
+
+    // request packet should have 12 byte header followed by 0 to 5 32-bit arguments
+    if (ret >= MTP_CONTAINER_HEADER_SIZE
+            && ret <= MTP_CONTAINER_HEADER_SIZE + 5 * sizeof(uint32_t)
+            && ((ret - MTP_CONTAINER_HEADER_SIZE) & 3) == 0) {
         mPacketSize = ret;
-    else
-        mPacketSize = 0;
+        mParameterCount = (ret - MTP_CONTAINER_HEADER_SIZE) / sizeof(uint32_t);
+    } else {
+        ALOGE("Malformed MTP request packet");
+        ret = -1;
+    }
     return ret;
 }
 #endif
diff --git a/media/mtp/MtpRequestPacket.h b/media/mtp/MtpRequestPacket.h
index 1201f11..79b798d 100644
--- a/media/mtp/MtpRequestPacket.h
+++ b/media/mtp/MtpRequestPacket.h
@@ -43,6 +43,10 @@
     inline MtpOperationCode    getOperationCode() const { return getContainerCode(); }
     inline void                setOperationCode(MtpOperationCode code)
                                                     { return setContainerCode(code); }
+    inline int                  getParameterCount() const { return mParameterCount; }
+
+private:
+    int     mParameterCount;
 };
 
 }; // namespace android
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index aa43967..07199e3 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -495,6 +495,9 @@
         mResponse.setParameter(1, mSessionID);
         return MTP_RESPONSE_SESSION_ALREADY_OPEN;
     }
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
+
     mSessionID = mRequest.getParameter(1);
     mSessionOpen = true;
 
@@ -529,6 +532,9 @@
 
     if (!mSessionOpen)
         return MTP_RESPONSE_SESSION_NOT_OPEN;
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
+
     MtpStorageID id = mRequest.getParameter(1);
     MtpStorage* storage = getStorage(id);
     if (!storage)
@@ -550,6 +556,8 @@
 MtpResponseCode MtpServer::doGetObjectPropsSupported() {
     if (!mSessionOpen)
         return MTP_RESPONSE_SESSION_NOT_OPEN;
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectFormat format = mRequest.getParameter(1);
     MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);
     mData.putAUInt16(properties);
@@ -560,6 +568,8 @@
 MtpResponseCode MtpServer::doGetObjectHandles() {
     if (!mSessionOpen)
         return MTP_RESPONSE_SESSION_NOT_OPEN;
+    if (mRequest.getParameterCount() < 3)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpStorageID storageID = mRequest.getParameter(1);      // 0xFFFFFFFF for all storage
     MtpObjectFormat format = mRequest.getParameter(2);      // 0 for all formats
     MtpObjectHandle parent = mRequest.getParameter(3);      // 0xFFFFFFFF for objects with no parent
@@ -577,6 +587,8 @@
 MtpResponseCode MtpServer::doGetNumObjects() {
     if (!mSessionOpen)
         return MTP_RESPONSE_SESSION_NOT_OPEN;
+    if (mRequest.getParameterCount() < 3)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpStorageID storageID = mRequest.getParameter(1);      // 0xFFFFFFFF for all storage
     MtpObjectFormat format = mRequest.getParameter(2);      // 0 for all formats
     MtpObjectHandle parent = mRequest.getParameter(3);      // 0xFFFFFFFF for objects with no parent
@@ -599,6 +611,8 @@
         return MTP_RESPONSE_SESSION_NOT_OPEN;
     if (!hasStorage())
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
 
     // FIXME - check for invalid object handle
@@ -617,9 +631,13 @@
         return MTP_RESPONSE_SESSION_NOT_OPEN;
     if (!hasStorage())
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpStorageID handle = mRequest.getParameter(1);
 
     MtpObjectHandleList* references = mData.getAUInt32();
+    if (!references)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpResponseCode result = mDatabase->setObjectReferences(handle, references);
     delete references;
     return result;
@@ -628,6 +646,8 @@
 MtpResponseCode MtpServer::doGetObjectPropValue() {
     if (!hasStorage())
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    if (mRequest.getParameterCount() < 2)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
     MtpObjectProperty property = mRequest.getParameter(2);
     ALOGV("GetObjectPropValue %d %s\n", handle,
@@ -639,6 +659,8 @@
 MtpResponseCode MtpServer::doSetObjectPropValue() {
     if (!hasStorage())
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    if (mRequest.getParameterCount() < 2)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
     MtpObjectProperty property = mRequest.getParameter(2);
     ALOGV("SetObjectPropValue %d %s\n", handle,
@@ -648,6 +670,8 @@
 }
 
 MtpResponseCode MtpServer::doGetDevicePropValue() {
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpDeviceProperty property = mRequest.getParameter(1);
     ALOGV("GetDevicePropValue %s\n",
             MtpDebug::getDevicePropCodeName(property));
@@ -656,6 +680,8 @@
 }
 
 MtpResponseCode MtpServer::doSetDevicePropValue() {
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpDeviceProperty property = mRequest.getParameter(1);
     ALOGV("SetDevicePropValue %s\n",
             MtpDebug::getDevicePropCodeName(property));
@@ -664,6 +690,8 @@
 }
 
 MtpResponseCode MtpServer::doResetDevicePropValue() {
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpDeviceProperty property = mRequest.getParameter(1);
     ALOGV("ResetDevicePropValue %s\n",
             MtpDebug::getDevicePropCodeName(property));
@@ -674,6 +702,8 @@
 MtpResponseCode MtpServer::doGetObjectPropList() {
     if (!hasStorage())
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    if (mRequest.getParameterCount() < 5)
+        return MTP_RESPONSE_INVALID_PARAMETER;
 
     MtpObjectHandle handle = mRequest.getParameter(1);
     // use uint32_t so we can support 0xFFFFFFFF
@@ -691,6 +721,8 @@
 MtpResponseCode MtpServer::doGetObjectInfo() {
     if (!hasStorage())
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
     MtpObjectInfo info(handle);
     MtpResponseCode result = mDatabase->getObjectInfo(handle, info);
@@ -732,6 +764,8 @@
 MtpResponseCode MtpServer::doGetObject() {
     if (!hasStorage())
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
     MtpString pathBuf;
     int64_t fileLength;
@@ -765,6 +799,8 @@
 }
 
 MtpResponseCode MtpServer::doGetThumb() {
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
     size_t thumbSize;
     void* thumb = mDatabase->getThumbnail(handle, thumbSize);
@@ -788,11 +824,19 @@
     uint32_t length;
     offset = mRequest.getParameter(2);
     if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) {
+        // MTP_OPERATION_GET_PARTIAL_OBJECT_64 takes 4 arguments
+        if (mRequest.getParameterCount() < 4)
+            return MTP_RESPONSE_INVALID_PARAMETER;
+
         // android extension with 64 bit offset
         uint64_t offset2 = mRequest.getParameter(3);
         offset = offset | (offset2 << 32);
         length = mRequest.getParameter(4);
     } else {
+        // MTP_OPERATION_GET_PARTIAL_OBJECT takes 3 arguments
+        if (mRequest.getParameterCount() < 3)
+            return MTP_RESPONSE_INVALID_PARAMETER;
+
         // standard GetPartialObject
         length = mRequest.getParameter(3);
     }
@@ -832,6 +876,11 @@
 
 MtpResponseCode MtpServer::doSendObjectInfo() {
     MtpString path;
+    uint16_t temp16;
+    uint32_t temp32;
+
+    if (mRequest.getParameterCount() < 2)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpStorageID storageID = mRequest.getParameter(1);
     MtpStorage* storage = getStorage(storageID);
     MtpObjectHandle parent = mRequest.getParameter(2);
@@ -853,25 +902,29 @@
     }
 
     // read only the fields we need
-    mData.getUInt32();  // storage ID
-    MtpObjectFormat format = mData.getUInt16();
-    mData.getUInt16();  // protection status
-    mSendObjectFileSize = mData.getUInt32();
-    mData.getUInt16();  // thumb format
-    mData.getUInt32();  // thumb compressed size
-    mData.getUInt32();  // thumb pix width
-    mData.getUInt32();  // thumb pix height
-    mData.getUInt32();  // image pix width
-    mData.getUInt32();  // image pix height
-    mData.getUInt32();  // image bit depth
-    mData.getUInt32();  // parent
-    uint16_t associationType = mData.getUInt16();
-    uint32_t associationDesc = mData.getUInt32();   // association desc
-    mData.getUInt32();  // sequence number
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // storage ID
+    if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
+    MtpObjectFormat format = temp16;
+    if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;  // protection status
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
+    mSendObjectFileSize = temp32;
+    if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;  // thumb format
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // thumb compressed size
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // thumb pix width
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // thumb pix height
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // image pix width
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // image pix height
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // image bit depth
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // parent
+    if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
+    uint16_t associationType = temp16;
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
+    uint32_t associationDesc = temp32;        // association desc
+    if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // sequence number
     MtpStringBuffer name, created, modified;
-    mData.getString(name);    // file name
-    mData.getString(created);      // date created
-    mData.getString(modified);     // date modified
+    if (!mData.getString(name)) return MTP_RESPONSE_INVALID_PARAMETER;    // file name
+    if (!mData.getString(created)) return MTP_RESPONSE_INVALID_PARAMETER;      // date created
+    if (!mData.getString(modified)) return MTP_RESPONSE_INVALID_PARAMETER;     // date modified
     // keywords follow
 
     ALOGV("name: %s format: %04X\n", (const char *)name, format);
@@ -1066,8 +1119,10 @@
 MtpResponseCode MtpServer::doDeleteObject() {
     if (!hasStorage())
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
-    MtpObjectFormat format = mRequest.getParameter(2);
+    MtpObjectFormat format;
     // FIXME - support deleting all objects if handle is 0xFFFFFFFF
     // FIXME - implement deleting objects by format
 
@@ -1087,6 +1142,8 @@
 }
 
 MtpResponseCode MtpServer::doGetObjectPropDesc() {
+    if (mRequest.getParameterCount() < 2)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectProperty propCode = mRequest.getParameter(1);
     MtpObjectFormat format = mRequest.getParameter(2);
     ALOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode),
@@ -1100,6 +1157,8 @@
 }
 
 MtpResponseCode MtpServer::doGetDevicePropDesc() {
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpDeviceProperty propCode = mRequest.getParameter(1);
     ALOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
     MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
@@ -1113,6 +1172,8 @@
 MtpResponseCode MtpServer::doSendPartialObject() {
     if (!hasStorage())
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+    if (mRequest.getParameterCount() < 4)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
     uint64_t offset = mRequest.getParameter(2);
     uint64_t offset2 = mRequest.getParameter(3);
@@ -1180,6 +1241,8 @@
 }
 
 MtpResponseCode MtpServer::doTruncateObject() {
+    if (mRequest.getParameterCount() < 3)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
     ObjectEdit* edit = getEditObject(handle);
     if (!edit) {
@@ -1199,6 +1262,8 @@
 }
 
 MtpResponseCode MtpServer::doBeginEditObject() {
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
     if (getEditObject(handle)) {
         ALOGE("object already open for edit in doBeginEditObject");
@@ -1223,6 +1288,8 @@
 }
 
 MtpResponseCode MtpServer::doEndEditObject() {
+    if (mRequest.getParameterCount() < 1)
+        return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
     ObjectEdit* edit = getEditObject(handle);
     if (!edit) {
diff --git a/media/mtp/MtpStorageInfo.cpp b/media/mtp/MtpStorageInfo.cpp
index 2b1a9ae..5d4ebbf 100644
--- a/media/mtp/MtpStorageInfo.cpp
+++ b/media/mtp/MtpStorageInfo.cpp
@@ -45,21 +45,23 @@
         free(mVolumeIdentifier);
 }
 
-void MtpStorageInfo::read(MtpDataPacket& packet) {
+bool MtpStorageInfo::read(MtpDataPacket& packet) {
     MtpStringBuffer string;
 
     // read the device info
-    mStorageType = packet.getUInt16();
-    mFileSystemType = packet.getUInt16();
-    mAccessCapability = packet.getUInt16();
-    mMaxCapacity = packet.getUInt64();
-    mFreeSpaceBytes = packet.getUInt64();
-    mFreeSpaceObjects = packet.getUInt32();
+    if (!packet.getUInt16(mStorageType)) return false;
+    if (!packet.getUInt16(mFileSystemType)) return false;
+    if (!packet.getUInt16(mAccessCapability)) return false;
+    if (!packet.getUInt64(mMaxCapacity)) return false;
+    if (!packet.getUInt64(mFreeSpaceBytes)) return false;
+    if (!packet.getUInt32(mFreeSpaceObjects)) return false;
 
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     mStorageDescription = strdup((const char *)string);
-    packet.getString(string);
+    if (!packet.getString(string)) return false;
     mVolumeIdentifier = strdup((const char *)string);
+
+    return true;
 }
 
 void MtpStorageInfo::print() {
diff --git a/media/mtp/MtpStorageInfo.h b/media/mtp/MtpStorageInfo.h
index 2cb626e..35a8189 100644
--- a/media/mtp/MtpStorageInfo.h
+++ b/media/mtp/MtpStorageInfo.h
@@ -39,7 +39,7 @@
                         MtpStorageInfo(MtpStorageID id);
     virtual             ~MtpStorageInfo();
 
-    void                read(MtpDataPacket& packet);
+    bool                read(MtpDataPacket& packet);
 
     void                print();
 };
diff --git a/media/mtp/MtpStringBuffer.cpp b/media/mtp/MtpStringBuffer.cpp
index f3420a4..df04694 100644
--- a/media/mtp/MtpStringBuffer.cpp
+++ b/media/mtp/MtpStringBuffer.cpp
@@ -123,11 +123,17 @@
     mByteCount = dest - mBuffer;
 }
 
-void MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
-    int count = packet->getUInt8();
+bool MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
+    uint8_t count;
+    if (!packet->getUInt8(count))
+        return false;
+
     uint8_t* dest = mBuffer;
     for (int i = 0; i < count; i++) {
-        uint16_t ch = packet->getUInt16();
+        uint16_t ch;
+
+        if (!packet->getUInt16(ch))
+            return false;
         if (ch >= 0x0800) {
             *dest++ = (uint8_t)(0xE0 | (ch >> 12));
             *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
@@ -142,6 +148,7 @@
     *dest++ = 0;
     mCharCount = count;
     mByteCount = dest - mBuffer;
+    return true;
 }
 
 void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
diff --git a/media/mtp/MtpStringBuffer.h b/media/mtp/MtpStringBuffer.h
index e5150df..85d91e8 100644
--- a/media/mtp/MtpStringBuffer.h
+++ b/media/mtp/MtpStringBuffer.h
@@ -46,7 +46,7 @@
     void            set(const char* src);
     void            set(const uint16_t* src);
 
-    void            readFromPacket(MtpDataPacket* packet);
+    bool            readFromPacket(MtpDataPacket* packet);
     void            writeToPacket(MtpDataPacket* packet) const;
 
     inline int      getCharCount() const { return mCharCount; }
diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp
index ed00b72..80c1c2f 100644
--- a/media/ndk/NdkMediaCodec.cpp
+++ b/media/ndk/NdkMediaCodec.cpp
@@ -116,7 +116,7 @@
 
         case kWhatStopActivityNotifications:
         {
-            uint32_t replyID;
+            sp<AReplyToken> replyID;
             msg->senderAwaitsResponse(&replyID);
 
             mCodec->mGeneration++;
@@ -136,7 +136,7 @@
 
 
 static void requestActivityNotification(AMediaCodec *codec) {
-    (new AMessage(kWhatRequestActivityNotifications, codec->mHandler->id()))->post();
+    (new AMessage(kWhatRequestActivityNotifications, codec->mHandler))->post();
 }
 
 extern "C" {
@@ -219,7 +219,7 @@
     if (ret != OK) {
         return translate_error(ret);
     }
-    mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler->id());
+    mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler);
     mData->mActivityNotification->setInt32("generation", mData->mGeneration);
     requestActivityNotification(mData);
     return AMEDIA_OK;
@@ -229,7 +229,7 @@
 media_status_t AMediaCodec_stop(AMediaCodec *mData) {
     media_status_t ret = translate_error(mData->mCodec->stop());
 
-    sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler->id());
+    sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler);
     sp<AMessage> response;
     msg->postAndAwaitResponse(&response);
     mData->mActivityNotification.clear();
@@ -352,7 +352,8 @@
 }
 
 //EXPORT
-media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback, void *userdata) {
+media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback,
+        void *userdata) {
     mData->mCallback = callback;
     mData->mCallbackUserData = userdata;
     return AMEDIA_OK;
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index db57d0b..0ecd64f 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -70,7 +70,8 @@
 }
 
 EXPORT
-media_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor *mData, int fd, off64_t offset, off64_t length) {
+media_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor *mData, int fd, off64_t offset,
+        off64_t length) {
     ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
     return translate_error(mData->mImpl->setDataSource(fd, offset, length));
 }
diff --git a/radio/Android.mk b/radio/Android.mk
new file mode 100644
index 0000000..ecbb8fd
--- /dev/null
+++ b/radio/Android.mk
@@ -0,0 +1,39 @@
+# Copyright 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	Radio.cpp \
+	IRadio.cpp \
+	IRadioClient.cpp \
+	IRadioService.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+	liblog \
+	libbinder \
+	libhardware \
+	libradio_metadata
+
+#LOCAL_C_INCLUDES += \
+	system/media/camera/include \
+	system/media/private/camera/include
+
+LOCAL_MODULE:= libradio
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/radio/IRadio.cpp b/radio/IRadio.cpp
new file mode 100644
index 0000000..242df77
--- /dev/null
+++ b/radio/IRadio.cpp
@@ -0,0 +1,344 @@
+/*
+**
+** 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 "IRadio"
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <binder/IMemory.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioService.h>
+#include <radio/IRadioClient.h>
+#include <system/radio.h>
+#include <system/radio_metadata.h>
+
+namespace android {
+
+enum {
+    DETACH = IBinder::FIRST_CALL_TRANSACTION,
+    SET_CONFIGURATION,
+    GET_CONFIGURATION,
+    SET_MUTE,
+    GET_MUTE,
+    SCAN,
+    STEP,
+    TUNE,
+    CANCEL,
+    GET_PROGRAM_INFORMATION,
+    HAS_CONTROL
+};
+
+class BpRadio: public BpInterface<IRadio>
+{
+public:
+    BpRadio(const sp<IBinder>& impl)
+        : BpInterface<IRadio>(impl)
+    {
+    }
+
+    void detach()
+    {
+        ALOGV("detach");
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        remote()->transact(DETACH, data, &reply);
+    }
+
+    virtual status_t setConfiguration(const struct radio_band_config *config)
+    {
+        Parcel data, reply;
+        if (config == NULL) {
+            return BAD_VALUE;
+        }
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        data.write(config, sizeof(struct radio_band_config));
+        status_t status = remote()->transact(SET_CONFIGURATION, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t getConfiguration(struct radio_band_config *config)
+    {
+        Parcel data, reply;
+        if (config == NULL) {
+            return BAD_VALUE;
+        }
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_CONFIGURATION, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            if (status == NO_ERROR) {
+                reply.read(config, sizeof(struct radio_band_config));
+            }
+        }
+        return status;
+    }
+
+    virtual status_t setMute(bool mute)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        data.writeInt32(mute ? 1 : 0);
+        status_t status = remote()->transact(SET_MUTE, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t getMute(bool *mute)
+    {
+        Parcel data, reply;
+        if (mute == NULL) {
+            return BAD_VALUE;
+        }
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_MUTE, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            if (status == NO_ERROR) {
+                int muteread = reply.readInt32();
+                *mute = muteread != 0;
+            }
+        }
+        return status;
+    }
+
+    virtual status_t scan(radio_direction_t direction, bool skipSubChannel)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        data.writeInt32(direction);
+        data.writeInt32(skipSubChannel ? 1 : 0);
+        status_t status = remote()->transact(SCAN, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t step(radio_direction_t direction, bool skipSubChannel)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        data.writeInt32(direction);
+        data.writeInt32(skipSubChannel ? 1 : 0);
+        status_t status = remote()->transact(STEP, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t tune(unsigned int channel, unsigned int subChannel)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        data.writeInt32(channel);
+        data.writeInt32(subChannel);
+        status_t status = remote()->transact(TUNE, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t cancel()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        status_t status = remote()->transact(CANCEL, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t getProgramInformation(struct radio_program_info *info)
+    {
+        Parcel data, reply;
+        if (info == NULL) {
+            return BAD_VALUE;
+        }
+        radio_metadata_t *metadata = info->metadata;
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_PROGRAM_INFORMATION, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            if (status == NO_ERROR) {
+                reply.read(info, sizeof(struct radio_program_info));
+                info->metadata = metadata;
+                if (metadata == NULL) {
+                    return status;
+                }
+                size_t size = (size_t)reply.readInt32();
+                if (size == 0) {
+                    return status;
+                }
+                metadata =
+                    (radio_metadata_t *)calloc(size / sizeof(unsigned int), sizeof(unsigned int));
+                if (metadata == NULL) {
+                    return NO_MEMORY;
+                }
+                reply.read(metadata, size);
+                status = radio_metadata_add_metadata(&info->metadata, metadata);
+                free(metadata);
+            }
+        }
+        return status;
+    }
+
+    virtual status_t hasControl(bool *hasControl)
+    {
+        Parcel data, reply;
+        if (hasControl == NULL) {
+            return BAD_VALUE;
+        }
+        data.writeInterfaceToken(IRadio::getInterfaceDescriptor());
+        status_t status = remote()->transact(HAS_CONTROL, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            if (status == NO_ERROR) {
+                *hasControl = reply.readInt32() != 0;
+            }
+        }
+        return status;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(Radio, "android.hardware.IRadio");
+
+// ----------------------------------------------------------------------
+
+status_t BnRadio::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case DETACH: {
+            ALOGV("DETACH");
+            CHECK_INTERFACE(IRadio, data, reply);
+            detach();
+            return NO_ERROR;
+        } break;
+        case SET_CONFIGURATION: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            struct radio_band_config config;
+            data.read(&config, sizeof(struct radio_band_config));
+            status_t status = setConfiguration(&config);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case GET_CONFIGURATION: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            struct radio_band_config config;
+            status_t status = getConfiguration(&config);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->write(&config, sizeof(struct radio_band_config));
+            }
+            return NO_ERROR;
+        }
+        case SET_MUTE: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            bool mute = data.readInt32() != 0;
+            status_t status = setMute(mute);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case GET_MUTE: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            bool mute;
+            status_t status = getMute(&mute);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32(mute ? 1 : 0);
+            }
+            return NO_ERROR;
+        }
+        case SCAN: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            radio_direction_t direction = (radio_direction_t)data.readInt32();
+            bool skipSubChannel = data.readInt32() == 1;
+            status_t status = scan(direction, skipSubChannel);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case STEP: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            radio_direction_t direction = (radio_direction_t)data.readInt32();
+            bool skipSubChannel = data.readInt32() == 1;
+            status_t status = step(direction, skipSubChannel);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case TUNE: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            unsigned int channel = (unsigned int)data.readInt32();
+            unsigned int subChannel = (unsigned int)data.readInt32();
+            status_t status = tune(channel, subChannel);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case CANCEL: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            status_t status = cancel();
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case GET_PROGRAM_INFORMATION: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            struct radio_program_info info;
+
+            status_t status = radio_metadata_allocate(&info.metadata, 0, 0);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            status = getProgramInformation(&info);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->write(&info, sizeof(struct radio_program_info));
+                int count = radio_metadata_get_count(info.metadata);
+                if (count > 0) {
+                    size_t size = radio_metadata_get_size(info.metadata);
+                    reply->writeInt32(size);
+                    reply->write(info.metadata, size);
+                } else {
+                    reply->writeInt32(0);
+                }
+            }
+            radio_metadata_deallocate(info.metadata);
+            return NO_ERROR;
+        }
+        case HAS_CONTROL: {
+            CHECK_INTERFACE(IRadio, data, reply);
+            bool control;
+            status_t status = hasControl(&control);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32(control ? 1 : 0);
+            }
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/radio/IRadioClient.cpp b/radio/IRadioClient.cpp
new file mode 100644
index 0000000..033ca49
--- /dev/null
+++ b/radio/IRadioClient.cpp
@@ -0,0 +1,75 @@
+/*
+**
+** 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.
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <radio/IRadioClient.h>
+
+namespace android {
+
+enum {
+    ON_EVENT = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpRadioClient: public BpInterface<IRadioClient>
+{
+
+public:
+    BpRadioClient(const sp<IBinder>& impl)
+        : BpInterface<IRadioClient>(impl)
+    {
+    }
+
+    virtual void onEvent(const sp<IMemory>& eventMemory)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadioClient::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(eventMemory));
+        remote()->transact(ON_EVENT,
+                           data,
+                           &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(RadioClient,
+                         "android.hardware.IRadioClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnRadioClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case ON_EVENT: {
+            CHECK_INTERFACE(IRadioClient, data, reply);
+            sp<IMemory> eventMemory = interface_cast<IMemory>(
+                data.readStrongBinder());
+            onEvent(eventMemory);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }   return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/radio/IRadioService.cpp b/radio/IRadioService.cpp
new file mode 100644
index 0000000..8c2b3ef
--- /dev/null
+++ b/radio/IRadioService.cpp
@@ -0,0 +1,181 @@
+/*
+**
+** 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 "BpRadioService"
+//
+#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <radio/IRadioService.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioClient.h>
+
+namespace android {
+
+enum {
+    LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
+    ATTACH,
+};
+
+#define MAX_ITEMS_PER_LIST 1024
+
+class BpRadioService: public BpInterface<IRadioService>
+{
+public:
+    BpRadioService(const sp<IBinder>& impl)
+        : BpInterface<IRadioService>(impl)
+    {
+    }
+
+    virtual status_t listModules(struct radio_properties *properties,
+                                 uint32_t *numModules)
+    {
+        if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
+            return BAD_VALUE;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
+        unsigned int numModulesReq = (properties == NULL) ? 0 : *numModules;
+        data.writeInt32(numModulesReq);
+        status_t status = remote()->transact(LIST_MODULES, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            *numModules = (unsigned int)reply.readInt32();
+        }
+        ALOGV("listModules() status %d got *numModules %d", status, *numModules);
+        if (status == NO_ERROR) {
+            if (numModulesReq > *numModules) {
+                numModulesReq = *numModules;
+            }
+            if (numModulesReq > 0) {
+                reply.read(properties, numModulesReq * sizeof(struct radio_properties));
+            }
+        }
+        return status;
+    }
+
+    virtual status_t attach(radio_handle_t handle,
+                            const sp<IRadioClient>& client,
+                            const struct radio_band_config *config,
+                            bool withAudio,
+                            sp<IRadio>& radio)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRadioService::getInterfaceDescriptor());
+        data.writeInt32(handle);
+        data.writeStrongBinder(IInterface::asBinder(client));
+        ALOGV("attach() config %p withAudio %d region %d type %d", config, withAudio, config->region, config->band.type);
+        if (config == NULL) {
+            data.writeInt32(0);
+        } else {
+            data.writeInt32(1);
+            data.write(config, sizeof(struct radio_band_config));
+        }
+        data.writeInt32(withAudio ? 1 : 0);
+        status_t status = remote()->transact(ATTACH, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = reply.readInt32();
+        if (reply.readInt32() != 0) {
+            radio = interface_cast<IRadio>(reply.readStrongBinder());
+        }
+        return status;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(RadioService, "android.hardware.IRadioService");
+
+// ----------------------------------------------------------------------
+
+status_t BnRadioService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case LIST_MODULES: {
+            CHECK_INTERFACE(IRadioService, data, reply);
+            unsigned int numModulesReq = data.readInt32();
+            if (numModulesReq > MAX_ITEMS_PER_LIST) {
+                numModulesReq = MAX_ITEMS_PER_LIST;
+            }
+            unsigned int numModules = numModulesReq;
+            struct radio_properties *properties =
+                    (struct radio_properties *)calloc(numModulesReq,
+                                                      sizeof(struct radio_properties));
+            if (properties == NULL) {
+                reply->writeInt32(NO_MEMORY);
+                reply->writeInt32(0);
+                return NO_ERROR;
+            }
+
+            status_t status = listModules(properties, &numModules);
+            reply->writeInt32(status);
+            reply->writeInt32(numModules);
+            ALOGV("LIST_MODULES status %d got numModules %d", status, numModules);
+
+            if (status == NO_ERROR) {
+                if (numModulesReq > numModules) {
+                    numModulesReq = numModules;
+                }
+                reply->write(properties,
+                             numModulesReq * sizeof(struct radio_properties));
+            }
+            free(properties);
+            return NO_ERROR;
+        } break;
+
+        case ATTACH: {
+            CHECK_INTERFACE(IRadioService, data, reply);
+            radio_handle_t handle = data.readInt32();
+            sp<IRadioClient> client =
+                    interface_cast<IRadioClient>(data.readStrongBinder());
+            struct radio_band_config config;
+            struct radio_band_config *configPtr = NULL;
+            if (data.readInt32() != 0) {
+                data.read(&config, sizeof(struct radio_band_config));
+                configPtr = &config;
+            }
+            bool withAudio = data.readInt32() != 0;
+            ALOGV("ATTACH configPtr %p withAudio %d", configPtr, withAudio);
+            sp<IRadio> radio;
+            status_t status = attach(handle, client, configPtr, withAudio, radio);
+            reply->writeInt32(status);
+            if (radio != 0) {
+                reply->writeInt32(1);
+                reply->writeStrongBinder(IInterface::asBinder(radio));
+            } else {
+                reply->writeInt32(0);
+            }
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/radio/Radio.cpp b/radio/Radio.cpp
new file mode 100644
index 0000000..e3554c2
--- /dev/null
+++ b/radio/Radio.cpp
@@ -0,0 +1,283 @@
+/*
+**
+** 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 "Radio"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IMemory.h>
+
+#include <radio/Radio.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioService.h>
+#include <radio/IRadioClient.h>
+#include <radio/RadioCallback.h>
+
+namespace android {
+
+namespace {
+    sp<IRadioService>          gRadioService;
+    const int                  kRadioServicePollDelay = 500000; // 0.5s
+    const char*                kRadioServiceName      = "media.radio";
+    Mutex                      gLock;
+
+    class DeathNotifier : public IBinder::DeathRecipient
+    {
+    public:
+        DeathNotifier() {
+        }
+
+        virtual void binderDied(const wp<IBinder>& who __unused) {
+            ALOGV("binderDied");
+            Mutex::Autolock _l(gLock);
+            gRadioService.clear();
+            ALOGW("Radio service died!");
+        }
+    };
+
+    sp<DeathNotifier>         gDeathNotifier;
+}; // namespace anonymous
+
+const sp<IRadioService>& Radio::getRadioService()
+{
+    Mutex::Autolock _l(gLock);
+    if (gRadioService.get() == 0) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder;
+        do {
+            binder = sm->getService(String16(kRadioServiceName));
+            if (binder != 0) {
+                break;
+            }
+            ALOGW("RadioService not published, waiting...");
+            usleep(kRadioServicePollDelay);
+        } while(true);
+        if (gDeathNotifier == NULL) {
+            gDeathNotifier = new DeathNotifier();
+        }
+        binder->linkToDeath(gDeathNotifier);
+        gRadioService = interface_cast<IRadioService>(binder);
+    }
+    ALOGE_IF(gRadioService == 0, "no RadioService!?");
+    return gRadioService;
+}
+
+// Static methods
+status_t Radio::listModules(struct radio_properties *properties,
+                            uint32_t *numModules)
+{
+    ALOGV("listModules()");
+    const sp<IRadioService>& service = getRadioService();
+    if (service == 0) {
+        return NO_INIT;
+    }
+    return service->listModules(properties, numModules);
+}
+
+sp<Radio> Radio::attach(radio_handle_t handle,
+                        const struct radio_band_config *config,
+                        bool withAudio,
+                        const sp<RadioCallback>& callback)
+{
+    ALOGV("attach()");
+    sp<Radio> radio;
+    const sp<IRadioService>& service = getRadioService();
+    if (service == 0) {
+        return radio;
+    }
+    radio = new Radio(handle, callback);
+    status_t status = service->attach(handle, radio, config, withAudio, radio->mIRadio);
+
+    if (status == NO_ERROR && radio->mIRadio != 0) {
+        IInterface::asBinder(radio->mIRadio)->linkToDeath(radio);
+    } else {
+        ALOGW("Error %d connecting to radio service", status);
+        radio.clear();
+    }
+    return radio;
+}
+
+
+
+// Radio
+Radio::Radio(radio_handle_t handle, const sp<RadioCallback>& callback)
+    : mHandle(handle), mCallback(callback)
+{
+}
+
+Radio::~Radio()
+{
+    if (mIRadio != 0) {
+        mIRadio->detach();
+    }
+}
+
+
+void Radio::detach() {
+    ALOGV("detach()");
+    Mutex::Autolock _l(mLock);
+    mCallback.clear();
+    if (mIRadio != 0) {
+        mIRadio->detach();
+        IInterface::asBinder(mIRadio)->unlinkToDeath(this);
+        mIRadio = 0;
+    }
+}
+
+status_t Radio::setConfiguration(const struct radio_band_config *config)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->setConfiguration(config);
+}
+
+status_t Radio::getConfiguration(struct radio_band_config *config)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->getConfiguration(config);
+}
+
+status_t Radio::setMute(bool mute)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->setMute(mute);
+}
+
+status_t Radio::getMute(bool *mute)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->getMute(mute);
+}
+
+status_t Radio::scan(radio_direction_t direction, bool skipSubchannel)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->scan(direction, skipSubchannel);
+}
+
+status_t Radio::step(radio_direction_t direction, bool skipSubchannel)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->step(direction, skipSubchannel);
+}
+
+status_t Radio::tune(unsigned int channel, unsigned int subChannel)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->tune(channel, subChannel);
+}
+
+status_t Radio::cancel()
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->cancel();
+}
+
+status_t Radio::getProgramInformation(struct radio_program_info *info)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->getProgramInformation(info);
+}
+
+status_t Radio::hasControl(bool *hasControl)
+{
+    Mutex::Autolock _l(mLock);
+    if (mIRadio == 0) {
+        return NO_INIT;
+    }
+    return mIRadio->hasControl(hasControl);
+}
+
+
+// BpRadioClient
+void Radio::onEvent(const sp<IMemory>& eventMemory)
+{
+    Mutex::Autolock _l(mLock);
+    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+        return;
+    }
+
+    struct radio_event *event = (struct radio_event *)eventMemory->pointer();
+    // restore local metadata pointer from offset
+    switch (event->type) {
+    case RADIO_EVENT_TUNED:
+    case RADIO_EVENT_AF_SWITCH:
+        if (event->info.metadata != NULL) {
+            event->info.metadata =
+                    (radio_metadata_t *)((char *)event + (size_t)event->info.metadata);
+        }
+        break;
+    case RADIO_EVENT_METADATA:
+        if (event->metadata != NULL) {
+            event->metadata =
+                    (radio_metadata_t *)((char *)event + (size_t)event->metadata);
+        }
+        break;
+    default:
+        break;
+    }
+
+    if (mCallback != 0) {
+        mCallback->onEvent(event);
+    }
+}
+
+
+//IBinder::DeathRecipient
+void Radio::binderDied(const wp<IBinder>& who __unused) {
+    Mutex::Autolock _l(mLock);
+    ALOGW("Radio server binder Died ");
+    mIRadio = 0;
+    struct radio_event event;
+    memset(&event, 0, sizeof(struct radio_event));
+    event.type = RADIO_EVENT_SERVER_DIED;
+    event.status = DEAD_OBJECT;
+    if (mCallback != 0) {
+        mCallback->onEvent(&event);
+    }
+}
+
+}; // namespace android
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 697fb37..642ff82 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -19,10 +19,22 @@
 # FIXME Move this library to frameworks/native
 LOCAL_MODULE := libserviceutility
 
-include $(BUILD_STATIC_LIBRARY)
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    liblog \
+    libbinder
+
+include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
 
+# Clang++ aborts on AudioMixer.cpp,
+# b/18373866, "do not know how to split this operator."
+ifeq ($(filter $(TARGET_ARCH),arm arm64),$(TARGET_ARCH))
+    LOCAL_CLANG := false
+endif
+
 LOCAL_SRC_FILES:=               \
     AudioFlinger.cpp            \
     Threads.cpp                 \
@@ -51,30 +63,31 @@
     libhardware \
     libhardware_legacy \
     libeffects \
-    libpowermanager
+    libpowermanager \
+    libserviceutility
 
 LOCAL_STATIC_LIBRARIES := \
     libscheduling_policy \
     libcpustats \
-    libmedia_helper \
-    libserviceutility
+    libmedia_helper
 
 LOCAL_MODULE:= libaudioflinger
 LOCAL_32_BIT_ONLY := true
 
-LOCAL_SRC_FILES += FastMixer.cpp FastMixerState.cpp AudioWatchdog.cpp
-LOCAL_SRC_FILES += FastThread.cpp FastThreadState.cpp
-LOCAL_SRC_FILES += FastCapture.cpp FastCaptureState.cpp
+LOCAL_SRC_FILES += \
+    AudioWatchdog.cpp        \
+    FastCapture.cpp          \
+    FastCaptureDumpState.cpp \
+    FastCaptureState.cpp     \
+    FastMixer.cpp            \
+    FastMixerDumpState.cpp   \
+    FastMixerState.cpp       \
+    FastThread.cpp           \
+    FastThreadDumpState.cpp  \
+    FastThreadState.cpp
 
 LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"'
 
-# Define ANDROID_SMP appropriately. Used to get inline tracing fast-path.
-ifeq ($(TARGET_CPU_SMP),true)
-    LOCAL_CFLAGS += -DANDROID_SMP=1
-else
-    LOCAL_CFLAGS += -DANDROID_SMP=0
-endif
-
 LOCAL_CFLAGS += -fvisibility=hidden
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 115b60c..461b5d3 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -185,7 +185,8 @@
     char value[PROPERTY_VALUE_MAX];
     bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);
     if (doLog) {
-        mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters", MemoryHeapBase::READ_ONLY);
+        mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
+                MemoryHeapBase::READ_ONLY);
     }
 
 #ifdef TEE_SINK
@@ -825,14 +826,20 @@
     if (ret != NO_ERROR) {
         return false;
     }
-
+    bool mute = true;
     bool state = AUDIO_MODE_INVALID;
     AutoMutex lock(mHardwareLock);
-    audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
     mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
-    dev->get_mic_mute(dev, &state);
+    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+        audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
+        status_t result = dev->get_mic_mute(dev, &state);
+        if (result == NO_ERROR) {
+            mute = mute && state;
+        }
+    }
     mHardwareStatus = AUDIO_HW_IDLE;
-    return state;
+
+    return mute;
 }
 
 status_t AudioFlinger::setMasterMute(bool muted)
@@ -894,6 +901,21 @@
     return mMasterMute;
 }
 
+status_t AudioFlinger::checkStreamType(audio_stream_type_t stream) const
+{
+    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+        ALOGW("setStreamVolume() invalid stream %d", stream);
+        return BAD_VALUE;
+    }
+    pid_t caller = IPCThreadState::self()->getCallingPid();
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT && caller != getpid_cached) {
+        ALOGW("setStreamVolume() pid %d cannot use internal stream type %d", caller, stream);
+        return PERMISSION_DENIED;
+    }
+
+    return NO_ERROR;
+}
+
 status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
         audio_io_handle_t output)
 {
@@ -902,10 +924,11 @@
         return PERMISSION_DENIED;
     }
 
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
-        ALOGE("setStreamVolume() invalid stream %d", stream);
-        return BAD_VALUE;
+    status_t status = checkStreamType(stream);
+    if (status != NO_ERROR) {
+        return status;
     }
+    ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to change AUDIO_STREAM_PATCH volume");
 
     AutoMutex lock(mLock);
     PlaybackThread *thread = NULL;
@@ -936,8 +959,13 @@
         return PERMISSION_DENIED;
     }
 
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT ||
-        uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
+    status_t status = checkStreamType(stream);
+    if (status != NO_ERROR) {
+        return status;
+    }
+    ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to mute AUDIO_STREAM_PATCH");
+
+    if (uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
         ALOGE("setStreamMute() invalid stream %d", stream);
         return BAD_VALUE;
     }
@@ -952,7 +980,8 @@
 
 float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    status_t status = checkStreamType(stream);
+    if (status != NO_ERROR) {
         return 0.0f;
     }
 
@@ -973,7 +1002,8 @@
 
 bool AudioFlinger::streamMute(audio_stream_type_t stream) const
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    status_t status = checkStreamType(stream);
+    if (status != NO_ERROR) {
         return true;
     }
 
@@ -1191,7 +1221,7 @@
 
             mNotificationClients.add(pid, notificationClient);
 
-            sp<IBinder> binder = client->asBinder();
+            sp<IBinder> binder = IInterface::asBinder(client);
             binder->linkToDeath(notificationClient);
             clientAdded = true;
         }
@@ -1413,13 +1443,6 @@
             goto Exit;
         }
 
-        if (deviceRequiresCaptureAudioOutputPermission(thread->inDevice())
-                && !captureAudioOutputAllowed()) {
-            ALOGE("openRecord() permission denied: capture not allowed");
-            lStatus = PERMISSION_DENIED;
-            goto Exit;
-        }
-
         pid_t pid = IPCThreadState::self()->getCallingPid();
         client = registerPid(pid);
 
@@ -1934,18 +1957,18 @@
 status_t AudioFlinger::openInput(audio_module_handle_t module,
                                           audio_io_handle_t *input,
                                           audio_config_t *config,
-                                          audio_devices_t *device,
+                                          audio_devices_t *devices,
                                           const String8& address,
                                           audio_source_t source,
                                           audio_input_flags_t flags)
 {
     Mutex::Autolock _l(mLock);
 
-    if (*device == AUDIO_DEVICE_NONE) {
+    if (*devices == AUDIO_DEVICE_NONE) {
         return BAD_VALUE;
     }
 
-    sp<RecordThread> thread = openInput_l(module, input, config, *device, address, source, flags);
+    sp<RecordThread> thread = openInput_l(module, input, config, *devices, address, source, flags);
 
     if (thread != 0) {
         // notify client processes of the new input creation
@@ -1958,12 +1981,12 @@
 sp<AudioFlinger::RecordThread> AudioFlinger::openInput_l(audio_module_handle_t module,
                                                          audio_io_handle_t *input,
                                                          audio_config_t *config,
-                                                         audio_devices_t device,
+                                                         audio_devices_t devices,
                                                          const String8& address,
                                                          audio_source_t source,
                                                          audio_input_flags_t flags)
 {
-    AudioHwDevice *inHwDev = findSuitableHwDev_l(module, device);
+    AudioHwDevice *inHwDev = findSuitableHwDev_l(module, devices);
     if (inHwDev == NULL) {
         *input = AUDIO_IO_HANDLE_NONE;
         return 0;
@@ -1976,7 +1999,7 @@
     audio_config_t halconfig = *config;
     audio_hw_device_t *inHwHal = inHwDev->hwDevice();
     audio_stream_in_t *inStream = NULL;
-    status_t status = inHwHal->open_input_stream(inHwHal, *input, device, &halconfig,
+    status_t status = inHwHal->open_input_stream(inHwHal, *input, devices, &halconfig,
                                         &inStream, flags, address.string(), source);
     ALOGV("openInput_l() openInputStream returned input %p, SamplingRate %d"
            ", Format %#x, Channels %x, flags %#x, status %d addr %s",
@@ -1998,7 +2021,7 @@
         // FIXME describe the change proposed by HAL (save old values so we can log them here)
         ALOGV("openInput_l() reopening with proposed sampling rate and channel mask");
         inStream = NULL;
-        status = inHwHal->open_input_stream(inHwHal, *input, device, &halconfig,
+        status = inHwHal->open_input_stream(inHwHal, *input, devices, &halconfig,
                                             &inStream, flags, address.string(), source);
         // FIXME log this new status; HAL should not propose any further changes
     }
@@ -2063,7 +2086,7 @@
                                   inputStream,
                                   *input,
                                   primaryOutputDevice_l(),
-                                  device
+                                  devices
 #ifdef TEE_SINK
                                   , teeSink
 #endif
@@ -2786,13 +2809,13 @@
 
 
 struct Entry {
-#define MAX_NAME 32     // %Y%m%d%H%M%S_%d.wav
-    char mName[MAX_NAME];
+#define TEE_MAX_FILENAME 32 // %Y%m%d%H%M%S_%d.wav = 4+2+2+2+2+2+1+1+4+1 = 21
+    char mFileName[TEE_MAX_FILENAME];
 };
 
 int comparEntry(const void *p1, const void *p2)
 {
-    return strcmp(((const Entry *) p1)->mName, ((const Entry *) p2)->mName);
+    return strcmp(((const Entry *) p1)->mFileName, ((const Entry *) p2)->mFileName);
 }
 
 #ifdef TEE_SINK
@@ -2811,11 +2834,11 @@
         DIR *dir = opendir(teePath);
         teePath[teePathLen++] = '/';
         if (dir != NULL) {
-#define MAX_SORT 20 // number of entries to sort
-#define MAX_KEEP 10 // number of entries to keep
-            struct Entry entries[MAX_SORT];
+#define TEE_MAX_SORT 20 // number of entries to sort
+#define TEE_MAX_KEEP 10 // number of entries to keep
+            struct Entry entries[TEE_MAX_SORT];
             size_t entryCount = 0;
-            while (entryCount < MAX_SORT) {
+            while (entryCount < TEE_MAX_SORT) {
                 struct dirent de;
                 struct dirent *result = NULL;
                 int rc = readdir_r(dir, &de, &result);
@@ -2832,17 +2855,17 @@
                 }
                 // ignore non .wav file entries
                 size_t nameLen = strlen(de.d_name);
-                if (nameLen <= 4 || nameLen >= MAX_NAME ||
+                if (nameLen <= 4 || nameLen >= TEE_MAX_FILENAME ||
                         strcmp(&de.d_name[nameLen - 4], ".wav")) {
                     continue;
                 }
-                strcpy(entries[entryCount++].mName, de.d_name);
+                strcpy(entries[entryCount++].mFileName, de.d_name);
             }
             (void) closedir(dir);
-            if (entryCount > MAX_KEEP) {
+            if (entryCount > TEE_MAX_KEEP) {
                 qsort(entries, entryCount, sizeof(Entry), comparEntry);
-                for (size_t i = 0; i < entryCount - MAX_KEEP; ++i) {
-                    strcpy(&teePath[teePathLen], entries[i].mName);
+                for (size_t i = 0; i < entryCount - TEE_MAX_KEEP; ++i) {
+                    strcpy(&teePath[teePathLen], entries[i].mFileName);
                     (void) unlink(teePath);
                 }
             }
@@ -2926,4 +2949,4 @@
     return BnAudioFlinger::onTransact(code, data, reply, flags);
 }
 
-}; // namespace android
+} // namespace android
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 4fb372d..7b76185 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -745,6 +745,8 @@
     void        closeInputInternal_l(sp<RecordThread> thread);
     void        setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId);
 
+    status_t    checkStreamType(audio_stream_type_t stream) const;
+
 #ifdef TEE_SINK
     // all record threads serially share a common tee sink, which is re-created on format change
     sp<NBAIO_Sink>   mRecordTeeSink;
@@ -794,9 +796,13 @@
 #undef INCLUDING_FROM_AUDIOFLINGER_H
 
 const char *formatToString(audio_format_t format);
+String8 inputFlagsToString(audio_input_flags_t flags);
+String8 outputFlagsToString(audio_output_flags_t flags);
+String8 devicesToString(audio_devices_t devices);
+const char *sourceToString(audio_source_t source);
 
 // ----------------------------------------------------------------------------
 
-}; // namespace android
+} // namespace android
 
 #endif // ANDROID_AUDIO_FLINGER_H
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 247f728..dddca02 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -341,11 +341,46 @@
     ALOGV("RemixBufferProvider(%p)(%#x, %#x, %#x) %zu %zu",
             this, format, inputChannelMask, outputChannelMask,
             mInputChannels, mOutputChannels);
-    // TODO: consider channel representation in index array formulation
-    // We ignore channel representation, and just use the bits.
-    memcpy_by_index_array_initialization(mIdxAry, ARRAY_SIZE(mIdxAry),
-            audio_channel_mask_get_bits(outputChannelMask),
-            audio_channel_mask_get_bits(inputChannelMask));
+
+    const audio_channel_representation_t inputRepresentation =
+            audio_channel_mask_get_representation(inputChannelMask);
+    const audio_channel_representation_t outputRepresentation =
+            audio_channel_mask_get_representation(outputChannelMask);
+    const uint32_t inputBits = audio_channel_mask_get_bits(inputChannelMask);
+    const uint32_t outputBits = audio_channel_mask_get_bits(outputChannelMask);
+
+    switch (inputRepresentation) {
+    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+        switch (outputRepresentation) {
+        case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+            memcpy_by_index_array_initialization(mIdxAry, ARRAY_SIZE(mIdxAry),
+                    outputBits, inputBits);
+            return;
+        case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+            // TODO: output channel index mask not currently allowed
+            // fall through
+        default:
+            break;
+        }
+        break;
+    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+        switch (outputRepresentation) {
+        case AUDIO_CHANNEL_REPRESENTATION_POSITION:
+            memcpy_by_index_array_initialization_src_index(mIdxAry, ARRAY_SIZE(mIdxAry),
+                    outputBits, inputBits);
+            return;
+        case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+            // TODO: output channel index mask not currently allowed
+            // fall through
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+    LOG_ALWAYS_FATAL("invalid channel mask conversion from %#x to %#x",
+            inputChannelMask, outputChannelMask);
 }
 
 void AudioMixer::RemixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
@@ -605,7 +640,10 @@
                     && mMixerChannelMask == AUDIO_CHANNEL_OUT_STEREO)) {
         return NO_ERROR;
     }
-    if (DownmixerBufferProvider::isMultichannelCapable()) {
+    // DownmixerBufferProvider is only used for position masks.
+    if (audio_channel_mask_get_representation(channelMask)
+                == AUDIO_CHANNEL_REPRESENTATION_POSITION
+            && DownmixerBufferProvider::isMultichannelCapable()) {
         DownmixerBufferProvider* pDbp = new DownmixerBufferProvider(channelMask,
                 mMixerChannelMask,
                 AUDIO_FORMAT_PCM_16_BIT /* TODO: use mMixerInFormat, now only PCM 16 */,
@@ -2262,4 +2300,4 @@
 }
 
 // ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
index 88e94c5..381036b 100644
--- a/services/audioflinger/AudioMixer.h
+++ b/services/audioflinger/AudioMixer.h
@@ -21,15 +21,15 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <hardware/audio_effect.h>
+#include <media/AudioBufferProvider.h>
+#include <media/nbaio/NBLog.h>
+#include <system/audio.h>
+#include <utils/Compat.h>
 #include <utils/threads.h>
 
-#include <media/AudioBufferProvider.h>
 #include "AudioResampler.h"
 
-#include <hardware/audio_effect.h>
-#include <system/audio.h>
-#include <media/nbaio/NBLog.h>
-
 // FIXME This is actually unity gain, which might not be max in future, expressed in U.12
 #define MAX_GAIN_INT AudioMixer::UNITY_GAIN_INT
 
@@ -58,7 +58,7 @@
     static const uint32_t MAX_NUM_CHANNELS_TO_DOWNMIX = AUDIO_CHANNEL_COUNT_MAX;
 
     static const uint16_t UNITY_GAIN_INT = 0x1000;
-    static const float    UNITY_GAIN_FLOAT = 1.0f;
+    static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;
 
     enum { // names
 
@@ -127,10 +127,16 @@
     size_t      getUnreleasedFrames(int name) const;
 
     static inline bool isValidPcmTrackFormat(audio_format_t format) {
-        return format == AUDIO_FORMAT_PCM_16_BIT ||
-                format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
-                format == AUDIO_FORMAT_PCM_32_BIT ||
-                format == AUDIO_FORMAT_PCM_FLOAT;
+        switch (format) {
+        case AUDIO_FORMAT_PCM_8_BIT:
+        case AUDIO_FORMAT_PCM_16_BIT:
+        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+        case AUDIO_FORMAT_PCM_32_BIT:
+        case AUDIO_FORMAT_PCM_FLOAT:
+            return true;
+        default:
+            return false;
+        }
     }
 
 private:
@@ -479,6 +485,6 @@
 };
 
 // ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
 
 #endif // ANDROID_AUDIO_MIXER_H
diff --git a/services/audioflinger/AudioMixerOps.h b/services/audioflinger/AudioMixerOps.h
index f7376a8..2678857 100644
--- a/services/audioflinger/AudioMixerOps.h
+++ b/services/audioflinger/AudioMixerOps.h
@@ -52,15 +52,12 @@
  *
  * For high precision audio, only the <TO, TI, TV> = <float, float, float>
  * needs to be accelerated. This is perhaps the easiest form to do quickly as well.
+ *
+ * A generic version is NOT defined to catch any mistake of using it.
  */
 
 template <typename TO, typename TI, typename TV>
-inline TO MixMul(TI value, TV volume) {
-    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(false);
-    // should not be here :-).
-    // To avoid mistakes, this template is always specialized.
-    return value * volume;
-}
+TO MixMul(TI value, TV volume);
 
 template <>
 inline int32_t MixMul<int32_t, int16_t, int16_t>(int16_t value, int16_t volume) {
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index 1f7a613..46e3d6c 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -29,14 +29,11 @@
 #include "AudioResamplerDyn.h"
 
 #ifdef __arm__
-#include <machine/cpu-features.h>
+    #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
 #endif
 
 namespace android {
 
-#ifdef __ARM_HAVE_HALFWORD_MULTIPLY // optimized asm option
-    #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
-#endif // __ARM_HAVE_HALFWORD_MULTIPLY
 // ----------------------------------------------------------------------------
 
 class AudioResamplerOrder1 : public AudioResampler {
diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h
index cdc6d92..863614a 100644
--- a/services/audioflinger/AudioResampler.h
+++ b/services/audioflinger/AudioResampler.h
@@ -19,7 +19,9 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+
 #include <cutils/compiler.h>
+#include <utils/Compat.h>
 
 #include <media/AudioBufferProvider.h>
 #include <system/audio.h>
@@ -47,7 +49,7 @@
         DYN_HIGH_QUALITY=7,
     };
 
-    static const float UNITY_GAIN_FLOAT = 1.0f;
+    static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;
 
     static AudioResampler* create(audio_format_t format, int inChannelCount,
             int32_t sampleRate, src_quality quality=DEFAULT_QUALITY);
@@ -168,7 +170,6 @@
 };
 
 // ----------------------------------------------------------------------------
-}
-; // namespace android
+} // namespace android
 
 #endif // ANDROID_AUDIO_RESAMPLER_H
diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp
index 8f14ff9..d3cbd1c 100644
--- a/services/audioflinger/AudioResamplerCubic.cpp
+++ b/services/audioflinger/AudioResamplerCubic.cpp
@@ -185,5 +185,4 @@
 }
 
 // ----------------------------------------------------------------------------
-}
-; // namespace android
+} // namespace android
diff --git a/services/audioflinger/AudioResamplerCubic.h b/services/audioflinger/AudioResamplerCubic.h
index b315da5..1ddc5f9 100644
--- a/services/audioflinger/AudioResamplerCubic.h
+++ b/services/audioflinger/AudioResamplerCubic.h
@@ -63,6 +63,6 @@
 };
 
 // ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
 
 #endif /*ANDROID_AUDIO_RESAMPLER_CUBIC_H*/
diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/services/audioflinger/AudioResamplerDyn.cpp
index 0eeb201..c21d4ca 100644
--- a/services/audioflinger/AudioResamplerDyn.cpp
+++ b/services/audioflinger/AudioResamplerDyn.cpp
@@ -618,4 +618,4 @@
 template class AudioResamplerDyn<int32_t, int16_t, int32_t>;
 
 // ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/services/audioflinger/AudioResamplerDyn.h b/services/audioflinger/AudioResamplerDyn.h
index e886a68..238b163 100644
--- a/services/audioflinger/AudioResamplerDyn.h
+++ b/services/audioflinger/AudioResamplerDyn.h
@@ -127,6 +127,6 @@
               void* mCoefBuffer;       // if a filter is created, this is not null
 };
 
-}; // namespace android
+} // namespace android
 
 #endif /*ANDROID_AUDIO_RESAMPLER_DYN_H*/
diff --git a/services/audioflinger/AudioResamplerFirGen.h b/services/audioflinger/AudioResamplerFirGen.h
index d024b2f..ad18965 100644
--- a/services/audioflinger/AudioResamplerFirGen.h
+++ b/services/audioflinger/AudioResamplerFirGen.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_AUDIO_RESAMPLER_FIR_GEN_H
 #define ANDROID_AUDIO_RESAMPLER_FIR_GEN_H
 
+#include "utils/Compat.h"
+
 namespace android {
 
 /*
@@ -187,22 +189,23 @@
 
 template <int N>
 struct I0Term {
-    static const double value = I0Term<N-1>::value / (4. * N * N);
+    static const CONSTEXPR double value = I0Term<N-1>::value / (4. * N * N);
 };
 
 template <>
 struct I0Term<0> {
-    static const double value = 1.;
+    static const CONSTEXPR double value = 1.;
 };
 
 template <int N>
 struct I0ATerm {
-    static const double value = I0ATerm<N-1>::value * (2.*N-1.) * (2.*N-1.) / (8. * N);
+    static const CONSTEXPR double value = I0ATerm<N-1>::value * (2.*N-1.) * (2.*N-1.) / (8. * N);
 };
 
 template <>
 struct I0ATerm<0> { // 1/sqrt(2*PI);
-    static const double value = 0.398942280401432677939946059934381868475858631164934657665925;
+    static const CONSTEXPR double value =
+            0.398942280401432677939946059934381868475858631164934657665925;
 };
 
 #if USE_HORNERS_METHOD
@@ -704,6 +707,6 @@
     }
 }
 
-}; // namespace android
+} // namespace android
 
 #endif /*ANDROID_AUDIO_RESAMPLER_FIR_GEN_H*/
diff --git a/services/audioflinger/AudioResamplerFirOps.h b/services/audioflinger/AudioResamplerFirOps.h
index bf2163f..658285d 100644
--- a/services/audioflinger/AudioResamplerFirOps.h
+++ b/services/audioflinger/AudioResamplerFirOps.h
@@ -25,7 +25,7 @@
 #define USE_INLINE_ASSEMBLY (false)
 #endif
 
-#if USE_INLINE_ASSEMBLY && defined(__ARM_NEON__)
+#if defined(__aarch64__) || defined(__ARM_NEON__)
 #define USE_NEON (true)
 #include <arm_neon.h>
 #else
@@ -158,6 +158,6 @@
 #endif
 }
 
-}; // namespace android
+} // namespace android
 
 #endif /*ANDROID_AUDIO_RESAMPLER_FIR_OPS_H*/
diff --git a/services/audioflinger/AudioResamplerFirProcess.h b/services/audioflinger/AudioResamplerFirProcess.h
index efc8055..176202e 100644
--- a/services/audioflinger/AudioResamplerFirProcess.h
+++ b/services/audioflinger/AudioResamplerFirProcess.h
@@ -174,7 +174,8 @@
  * Process() calls ProcessBase() with TFUNC = InterpCompute, for interpolated phase.
  */
 
-template <int CHANNELS, int STRIDE, typename TFUNC, typename TC, typename TI, typename TO, typename TINTERP>
+template <int CHANNELS, int STRIDE, typename TFUNC, typename TC, typename TI, typename TO,
+        typename TINTERP>
 static inline
 void ProcessBase(TO* const out,
         size_t count,
@@ -242,6 +243,9 @@
     }
 }
 
+/* Calculates a single output frame from a polyphase resampling filter.
+ * See Process() for parameter details.
+ */
 template <int CHANNELS, int STRIDE, typename TC, typename TI, typename TO>
 static inline
 void ProcessL(TO* const out,
@@ -255,6 +259,39 @@
     ProcessBase<CHANNELS, STRIDE, InterpNull>(out, count, coefsP, coefsN, sP, sN, 0, volumeLR);
 }
 
+/*
+ * Calculates a single output frame from a polyphase resampling filter,
+ * with filter phase interpolation.
+ *
+ * @param out should point to the output buffer with space for at least one output frame.
+ *
+ * @param count should be half the size of the total filter length (halfNumCoefs), as we
+ * use symmetry in filter coefficients to evaluate two dot products.
+ *
+ * @param coefsP is one phase of the polyphase filter bank of size halfNumCoefs, corresponding
+ * to the positive sP.
+ *
+ * @param coefsN is one phase of the polyphase filter bank of size halfNumCoefs, corresponding
+ * to the negative sN.
+ *
+ * @param coefsP1 is the next phase of coefsP (used for interpolation).
+ *
+ * @param coefsN1 is the next phase of coefsN (used for interpolation).
+ *
+ * @param sP is the positive half of the coefficients (as viewed by a convolution),
+ * starting at the original samples pointer and decrementing (by CHANNELS).
+ *
+ * @param sN is the negative half of the samples (as viewed by a convolution),
+ * starting at the original samples pointer + CHANNELS and incrementing (by CHANNELS).
+ *
+ * @param lerpP The fractional siting between the polyphase indices is given by the bits
+ * below coefShift. See fir() for details.
+ *
+ * @param volumeLR is a pointer to an array of two 32 bit volume values, one per stereo channel,
+ * expressed as a S32 integer or float.  A negative value inverts the channel 180 degrees.
+ * The pointer volumeLR should be aligned to a minimum of 8 bytes.
+ * A typical value for volume is 0x1000 to align to a unity gain output of 20.12.
+ */
 template <int CHANNELS, int STRIDE, typename TC, typename TI, typename TO, typename TINTERP>
 static inline
 void Process(TO* const out,
@@ -268,11 +305,12 @@
         TINTERP lerpP,
         const TO* const volumeLR)
 {
-    ProcessBase<CHANNELS, STRIDE, InterpCompute>(out, count, coefsP, coefsN, sP, sN, lerpP, volumeLR);
+    ProcessBase<CHANNELS, STRIDE, InterpCompute>(out, count, coefsP, coefsN, sP, sN, lerpP,
+            volumeLR);
 }
 
 /*
- * Calculates a single output frame (two samples) from input sample pointer.
+ * Calculates a single output frame from input sample pointer.
  *
  * This sets up the params for the accelerated Process() and ProcessL()
  * functions to do the appropriate dot products.
@@ -307,7 +345,7 @@
  * the positive half of the filter is dot product from samples to samples-halfNumCoefs+1.
  *
  * @param volumeLR is a pointer to an array of two 32 bit volume values, one per stereo channel,
- * expressed as a S32 integer.  A negative value inverts the channel 180 degrees.
+ * expressed as a S32 integer or float.  A negative value inverts the channel 180 degrees.
  * The pointer volumeLR should be aligned to a minimum of 8 bytes.
  * A typical value for volume is 0x1000 to align to a unity gain output of 20.12.
  *
@@ -396,6 +434,6 @@
     }
 }
 
-}; // namespace android
+} // namespace android
 
 #endif /*ANDROID_AUDIO_RESAMPLER_FIR_PROCESS_H*/
diff --git a/services/audioflinger/AudioResamplerFirProcessNeon.h b/services/audioflinger/AudioResamplerFirProcessNeon.h
index f311cef..3de9edd 100644
--- a/services/audioflinger/AudioResamplerFirProcessNeon.h
+++ b/services/audioflinger/AudioResamplerFirProcessNeon.h
@@ -22,14 +22,35 @@
 // depends on AudioResamplerFirOps.h, AudioResamplerFirProcess.h
 
 #if USE_NEON
+
+// use intrinsics if inline arm32 assembly is not possible
+#if !USE_INLINE_ASSEMBLY
+#define USE_INTRINSIC
+#endif
+
+// following intrinsics available only on ARM 64 bit ACLE
+#ifndef __aarch64__
+#undef vld1q_f32_x2
+#undef vld1q_s32_x2
+#endif
+
+#define TO_STRING2(x) #x
+#define TO_STRING(x) TO_STRING2(x)
+// uncomment to print GCC version, may be relevant for intrinsic optimizations
+/* #pragma message ("GCC version: " TO_STRING(__GNUC__) \
+        "." TO_STRING(__GNUC_MINOR__) \
+        "." TO_STRING(__GNUC_PATCHLEVEL__)) */
+
 //
-// NEON specializations are enabled for Process() and ProcessL()
+// NEON specializations are enabled for Process() and ProcessL() in AudioResamplerFirProcess.h
 //
-// TODO: Stride 16 and Stride 8 can be combined with one pass stride 8 (if necessary)
-// and looping stride 16 (or vice versa). This has some polyphase coef data alignment
-// issues with S16 coefs. Consider this later.
+// Two variants are presented here:
+// ARM NEON inline assembly which appears up to 10-15% faster than intrinsics (gcc 4.9) for arm32.
+// ARM NEON intrinsics which can also be used by arm64 and x86/64 with NEON header.
+//
 
 // Macros to save a mono/stereo accumulator sample in q0 (and q4) as stereo out.
+// These are only used for inline assembly.
 #define ASSEMBLY_ACCUMULATE_MONO \
         "vld1.s32       {d2}, [%[vLR]:64]        \n"/* (1) load volumes */\
         "vld1.s32       {d3}, %[out]             \n"/* (2) unaligned load the output */\
@@ -49,6 +70,458 @@
         "vqadd.s32      d3, d3, d0               \n"/* (1+4d) accumulate result (saturating)*/\
         "vst1.s32       {d3}, %[out]             \n"/* (2+2d)store result*/
 
+template <int CHANNELS, int STRIDE, bool FIXED>
+static inline void ProcessNeonIntrinsic(int32_t* out,
+        int count,
+        const int16_t* coefsP,
+        const int16_t* coefsN,
+        const int16_t* sP,
+        const int16_t* sN,
+        const int32_t* volumeLR,
+        uint32_t lerpP,
+        const int16_t* coefsP1,
+        const int16_t* coefsN1)
+{
+    ALOG_ASSERT(count > 0 && (count & 7) == 0); // multiple of 8
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(CHANNELS == 1 || CHANNELS == 2);
+
+    sP -= CHANNELS*((STRIDE>>1)-1);
+    coefsP = (const int16_t*)__builtin_assume_aligned(coefsP, 16);
+    coefsN = (const int16_t*)__builtin_assume_aligned(coefsN, 16);
+
+    int16x4_t interp;
+    if (!FIXED) {
+        interp = vdup_n_s16(lerpP);
+        //interp = (int16x4_t)vset_lane_s32 ((int32x2_t)lerpP, interp, 0);
+        coefsP1 = (const int16_t*)__builtin_assume_aligned(coefsP1, 16);
+        coefsN1 = (const int16_t*)__builtin_assume_aligned(coefsN1, 16);
+    }
+    int32x4_t accum, accum2;
+    // warning uninitialized if we use veorq_s32
+    // (alternative to below) accum = veorq_s32(accum, accum);
+    accum = vdupq_n_s32(0);
+    if (CHANNELS == 2) {
+        // (alternative to below) accum2 = veorq_s32(accum2, accum2);
+        accum2 = vdupq_n_s32(0);
+    }
+    do {
+        int16x8_t posCoef = vld1q_s16(coefsP);
+        coefsP += 8;
+        int16x8_t negCoef = vld1q_s16(coefsN);
+        coefsN += 8;
+        if (!FIXED) { // interpolate
+            int16x8_t posCoef1 = vld1q_s16(coefsP1);
+            coefsP1 += 8;
+            int16x8_t negCoef1 = vld1q_s16(coefsN1);
+            coefsN1 += 8;
+
+            posCoef1 = vsubq_s16(posCoef1, posCoef);
+            negCoef = vsubq_s16(negCoef, negCoef1);
+
+            posCoef1 = vqrdmulhq_lane_s16(posCoef1, interp, 0);
+            negCoef = vqrdmulhq_lane_s16(negCoef, interp, 0);
+
+            posCoef = vaddq_s16(posCoef, posCoef1);
+            negCoef = vaddq_s16(negCoef, negCoef1);
+        }
+        switch (CHANNELS) {
+        case 1: {
+            int16x8_t posSamp = vld1q_s16(sP);
+            int16x8_t negSamp = vld1q_s16(sN);
+            sN += 8;
+            posSamp = vrev64q_s16(posSamp);
+
+            // dot product
+            accum = vmlal_s16(accum, vget_low_s16(posSamp), vget_high_s16(posCoef)); // reversed
+            accum = vmlal_s16(accum, vget_high_s16(posSamp), vget_low_s16(posCoef)); // reversed
+            accum = vmlal_s16(accum, vget_low_s16(negSamp), vget_low_s16(negCoef));
+            accum = vmlal_s16(accum, vget_high_s16(negSamp), vget_high_s16(negCoef));
+            sP -= 8;
+        } break;
+        case 2: {
+            int16x8x2_t posSamp = vld2q_s16(sP);
+            int16x8x2_t negSamp = vld2q_s16(sN);
+            sN += 16;
+            posSamp.val[0] = vrev64q_s16(posSamp.val[0]);
+            posSamp.val[1] = vrev64q_s16(posSamp.val[1]);
+
+            // dot product
+            accum = vmlal_s16(accum, vget_low_s16(posSamp.val[0]), vget_high_s16(posCoef)); // r
+            accum = vmlal_s16(accum, vget_high_s16(posSamp.val[0]), vget_low_s16(posCoef)); // r
+            accum2 = vmlal_s16(accum2, vget_low_s16(posSamp.val[1]), vget_high_s16(posCoef)); // r
+            accum2 = vmlal_s16(accum2, vget_high_s16(posSamp.val[1]), vget_low_s16(posCoef)); // r
+            accum = vmlal_s16(accum, vget_low_s16(negSamp.val[0]), vget_low_s16(negCoef));
+            accum = vmlal_s16(accum, vget_high_s16(negSamp.val[0]), vget_high_s16(negCoef));
+            accum2 = vmlal_s16(accum2, vget_low_s16(negSamp.val[1]), vget_low_s16(negCoef));
+            accum2 = vmlal_s16(accum2, vget_high_s16(negSamp.val[1]), vget_high_s16(negCoef));
+            sP -= 16;
+        }
+        } break;
+    } while (count -= 8);
+
+    // multiply by volume and save
+    volumeLR = (const int32_t*)__builtin_assume_aligned(volumeLR, 8);
+    int32x2_t vLR = vld1_s32(volumeLR);
+    int32x2_t outSamp = vld1_s32(out);
+    // combine and funnel down accumulator
+    int32x2_t outAccum = vpadd_s32(vget_low_s32(accum), vget_high_s32(accum));
+    if (CHANNELS == 1) {
+        // duplicate accum to both L and R
+        outAccum = vpadd_s32(outAccum, outAccum);
+    } else if (CHANNELS == 2) {
+        // accum2 contains R, fold in
+        int32x2_t outAccum2 = vpadd_s32(vget_low_s32(accum2), vget_high_s32(accum2));
+        outAccum = vpadd_s32(outAccum, outAccum2);
+    }
+    outAccum = vqrdmulh_s32(outAccum, vLR);
+    outSamp = vqadd_s32(outSamp, outAccum);
+    vst1_s32(out, outSamp);
+}
+
+template <int CHANNELS, int STRIDE, bool FIXED>
+static inline void ProcessNeonIntrinsic(int32_t* out,
+        int count,
+        const int32_t* coefsP,
+        const int32_t* coefsN,
+        const int16_t* sP,
+        const int16_t* sN,
+        const int32_t* volumeLR,
+        uint32_t lerpP,
+        const int32_t* coefsP1,
+        const int32_t* coefsN1)
+{
+    ALOG_ASSERT(count > 0 && (count & 7) == 0); // multiple of 8
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(CHANNELS == 1 || CHANNELS == 2);
+
+    sP -= CHANNELS*((STRIDE>>1)-1);
+    coefsP = (const int32_t*)__builtin_assume_aligned(coefsP, 16);
+    coefsN = (const int32_t*)__builtin_assume_aligned(coefsN, 16);
+
+    int32x2_t interp;
+    if (!FIXED) {
+        interp = vdup_n_s32(lerpP);
+        coefsP1 = (const int32_t*)__builtin_assume_aligned(coefsP1, 16);
+        coefsN1 = (const int32_t*)__builtin_assume_aligned(coefsN1, 16);
+    }
+    int32x4_t accum, accum2;
+    // warning uninitialized if we use veorq_s32
+    // (alternative to below) accum = veorq_s32(accum, accum);
+    accum = vdupq_n_s32(0);
+    if (CHANNELS == 2) {
+        // (alternative to below) accum2 = veorq_s32(accum2, accum2);
+        accum2 = vdupq_n_s32(0);
+    }
+    do {
+#ifdef vld1q_s32_x2
+        int32x4x2_t posCoef = vld1q_s32_x2(coefsP);
+        coefsP += 8;
+        int32x4x2_t negCoef = vld1q_s32_x2(coefsN);
+        coefsN += 8;
+#else
+        int32x4x2_t posCoef;
+        posCoef.val[0] = vld1q_s32(coefsP);
+        coefsP += 4;
+        posCoef.val[1] = vld1q_s32(coefsP);
+        coefsP += 4;
+        int32x4x2_t negCoef;
+        negCoef.val[0] = vld1q_s32(coefsN);
+        coefsN += 4;
+        negCoef.val[1] = vld1q_s32(coefsN);
+        coefsN += 4;
+#endif
+        if (!FIXED) { // interpolate
+#ifdef vld1q_s32_x2
+            int32x4x2_t posCoef1 = vld1q_s32_x2(coefsP1);
+            coefsP1 += 8;
+            int32x4x2_t negCoef1 = vld1q_s32_x2(coefsN1);
+            coefsN1 += 8;
+#else
+            int32x4x2_t posCoef1;
+            posCoef1.val[0] = vld1q_s32(coefsP1);
+            coefsP1 += 4;
+            posCoef1.val[1] = vld1q_s32(coefsP1);
+            coefsP1 += 4;
+            int32x4x2_t negCoef1;
+            negCoef1.val[0] = vld1q_s32(coefsN1);
+            coefsN1 += 4;
+            negCoef1.val[1] = vld1q_s32(coefsN1);
+            coefsN1 += 4;
+#endif
+
+            posCoef1.val[0] = vsubq_s32(posCoef1.val[0], posCoef.val[0]);
+            posCoef1.val[1] = vsubq_s32(posCoef1.val[1], posCoef.val[1]);
+            negCoef.val[0] = vsubq_s32(negCoef.val[0], negCoef1.val[0]);
+            negCoef.val[1] = vsubq_s32(negCoef.val[1], negCoef1.val[1]);
+
+            posCoef1.val[0] = vqrdmulhq_lane_s32(posCoef1.val[0], interp, 0);
+            posCoef1.val[1] = vqrdmulhq_lane_s32(posCoef1.val[1], interp, 0);
+            negCoef.val[0] = vqrdmulhq_lane_s32(negCoef.val[0], interp, 0);
+            negCoef.val[1] = vqrdmulhq_lane_s32(negCoef.val[1], interp, 0);
+
+            posCoef.val[0] = vaddq_s32(posCoef.val[0], posCoef1.val[0]);
+            posCoef.val[1] = vaddq_s32(posCoef.val[1], posCoef1.val[1]);
+            negCoef.val[0] = vaddq_s32(negCoef.val[0], negCoef1.val[0]);
+            negCoef.val[1] = vaddq_s32(negCoef.val[1], negCoef1.val[1]);
+        }
+        switch (CHANNELS) {
+        case 1: {
+            int16x8_t posSamp = vld1q_s16(sP);
+            int16x8_t negSamp = vld1q_s16(sN);
+            sN += 8;
+            posSamp = vrev64q_s16(posSamp);
+
+            int32x4_t posSamp0 = vshll_n_s16(vget_low_s16(posSamp), 15);
+            int32x4_t posSamp1 = vshll_n_s16(vget_high_s16(posSamp), 15);
+            int32x4_t negSamp0 = vshll_n_s16(vget_low_s16(negSamp), 15);
+            int32x4_t negSamp1 = vshll_n_s16(vget_high_s16(negSamp), 15);
+
+            // dot product
+            posSamp0 = vqrdmulhq_s32(posSamp0, posCoef.val[1]); // reversed
+            posSamp1 = vqrdmulhq_s32(posSamp1, posCoef.val[0]); // reversed
+            negSamp0 = vqrdmulhq_s32(negSamp0, negCoef.val[0]);
+            negSamp1 = vqrdmulhq_s32(negSamp1, negCoef.val[1]);
+
+            accum = vaddq_s32(accum, posSamp0);
+            negSamp0 = vaddq_s32(negSamp0, negSamp1);
+            accum = vaddq_s32(accum, posSamp1);
+            accum = vaddq_s32(accum, negSamp0);
+
+            sP -= 8;
+        } break;
+        case 2: {
+            int16x8x2_t posSamp = vld2q_s16(sP);
+            int16x8x2_t negSamp = vld2q_s16(sN);
+            sN += 16;
+            posSamp.val[0] = vrev64q_s16(posSamp.val[0]);
+            posSamp.val[1] = vrev64q_s16(posSamp.val[1]);
+
+            // left
+            int32x4_t posSamp0 = vshll_n_s16(vget_low_s16(posSamp.val[0]), 15);
+            int32x4_t posSamp1 = vshll_n_s16(vget_high_s16(posSamp.val[0]), 15);
+            int32x4_t negSamp0 = vshll_n_s16(vget_low_s16(negSamp.val[0]), 15);
+            int32x4_t negSamp1 = vshll_n_s16(vget_high_s16(negSamp.val[0]), 15);
+
+            // dot product
+            posSamp0 = vqrdmulhq_s32(posSamp0, posCoef.val[1]); // reversed
+            posSamp1 = vqrdmulhq_s32(posSamp1, posCoef.val[0]); // reversed
+            negSamp0 = vqrdmulhq_s32(negSamp0, negCoef.val[0]);
+            negSamp1 = vqrdmulhq_s32(negSamp1, negCoef.val[1]);
+
+            accum = vaddq_s32(accum, posSamp0);
+            negSamp0 = vaddq_s32(negSamp0, negSamp1);
+            accum = vaddq_s32(accum, posSamp1);
+            accum = vaddq_s32(accum, negSamp0);
+
+            // right
+            posSamp0 = vshll_n_s16(vget_low_s16(posSamp.val[1]), 15);
+            posSamp1 = vshll_n_s16(vget_high_s16(posSamp.val[1]), 15);
+            negSamp0 = vshll_n_s16(vget_low_s16(negSamp.val[1]), 15);
+            negSamp1 = vshll_n_s16(vget_high_s16(negSamp.val[1]), 15);
+
+            // dot product
+            posSamp0 = vqrdmulhq_s32(posSamp0, posCoef.val[1]); // reversed
+            posSamp1 = vqrdmulhq_s32(posSamp1, posCoef.val[0]); // reversed
+            negSamp0 = vqrdmulhq_s32(negSamp0, negCoef.val[0]);
+            negSamp1 = vqrdmulhq_s32(negSamp1, negCoef.val[1]);
+
+            accum2 = vaddq_s32(accum2, posSamp0);
+            negSamp0 = vaddq_s32(negSamp0, negSamp1);
+            accum2 = vaddq_s32(accum2, posSamp1);
+            accum2 = vaddq_s32(accum2, negSamp0);
+
+            sP -= 16;
+        } break;
+        }
+    } while (count -= 8);
+
+    // multiply by volume and save
+    volumeLR = (const int32_t*)__builtin_assume_aligned(volumeLR, 8);
+    int32x2_t vLR = vld1_s32(volumeLR);
+    int32x2_t outSamp = vld1_s32(out);
+    // combine and funnel down accumulator
+    int32x2_t outAccum = vpadd_s32(vget_low_s32(accum), vget_high_s32(accum));
+    if (CHANNELS == 1) {
+        // duplicate accum to both L and R
+        outAccum = vpadd_s32(outAccum, outAccum);
+    } else if (CHANNELS == 2) {
+        // accum2 contains R, fold in
+        int32x2_t outAccum2 = vpadd_s32(vget_low_s32(accum2), vget_high_s32(accum2));
+        outAccum = vpadd_s32(outAccum, outAccum2);
+    }
+    outAccum = vqrdmulh_s32(outAccum, vLR);
+    outSamp = vqadd_s32(outSamp, outAccum);
+    vst1_s32(out, outSamp);
+}
+
+template <int CHANNELS, int STRIDE, bool FIXED>
+static inline void ProcessNeonIntrinsic(float* out,
+        int count,
+        const float* coefsP,
+        const float* coefsN,
+        const float* sP,
+        const float* sN,
+        const float* volumeLR,
+        float lerpP,
+        const float* coefsP1,
+        const float* coefsN1)
+{
+    ALOG_ASSERT(count > 0 && (count & 7) == 0); // multiple of 8
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(CHANNELS == 1 || CHANNELS == 2);
+
+    sP -= CHANNELS*((STRIDE>>1)-1);
+    coefsP = (const float*)__builtin_assume_aligned(coefsP, 16);
+    coefsN = (const float*)__builtin_assume_aligned(coefsN, 16);
+
+    float32x2_t interp;
+    if (!FIXED) {
+        interp = vdup_n_f32(lerpP);
+        coefsP1 = (const float*)__builtin_assume_aligned(coefsP1, 16);
+        coefsN1 = (const float*)__builtin_assume_aligned(coefsN1, 16);
+    }
+    float32x4_t accum, accum2;
+    // warning uninitialized if we use veorq_s32
+    // (alternative to below) accum = veorq_s32(accum, accum);
+    accum = vdupq_n_f32(0);
+    if (CHANNELS == 2) {
+        // (alternative to below) accum2 = veorq_s32(accum2, accum2);
+        accum2 = vdupq_n_f32(0);
+    }
+    do {
+#ifdef vld1q_f32_x2
+        float32x4x2_t posCoef = vld1q_f32_x2(coefsP);
+        coefsP += 8;
+        float32x4x2_t negCoef = vld1q_f32_x2(coefsN);
+        coefsN += 8;
+#else
+        float32x4x2_t posCoef;
+        posCoef.val[0] = vld1q_f32(coefsP);
+        coefsP += 4;
+        posCoef.val[1] = vld1q_f32(coefsP);
+        coefsP += 4;
+        float32x4x2_t negCoef;
+        negCoef.val[0] = vld1q_f32(coefsN);
+        coefsN += 4;
+        negCoef.val[1] = vld1q_f32(coefsN);
+        coefsN += 4;
+#endif
+        if (!FIXED) { // interpolate
+#ifdef vld1q_f32_x2
+            float32x4x2_t posCoef1 = vld1q_f32_x2(coefsP1);
+            coefsP1 += 8;
+            float32x4x2_t negCoef1 = vld1q_f32_x2(coefsN1);
+            coefsN1 += 8;
+#else
+            float32x4x2_t posCoef1;
+            posCoef1.val[0] = vld1q_f32(coefsP1);
+            coefsP1 += 4;
+            posCoef1.val[1] = vld1q_f32(coefsP1);
+            coefsP1 += 4;
+            float32x4x2_t negCoef1;
+            negCoef1.val[0] = vld1q_f32(coefsN1);
+            coefsN1 += 4;
+            negCoef1.val[1] = vld1q_f32(coefsN1);
+            coefsN1 += 4;
+#endif
+            posCoef1.val[0] = vsubq_f32(posCoef1.val[0], posCoef.val[0]);
+            posCoef1.val[1] = vsubq_f32(posCoef1.val[1], posCoef.val[1]);
+            negCoef.val[0] = vsubq_f32(negCoef.val[0], negCoef1.val[0]);
+            negCoef.val[1] = vsubq_f32(negCoef.val[1], negCoef1.val[1]);
+
+            posCoef.val[0] = vmlaq_lane_f32(posCoef.val[0], posCoef1.val[0], interp, 0);
+            posCoef.val[1] = vmlaq_lane_f32(posCoef.val[1], posCoef1.val[1], interp, 0);
+            negCoef.val[0] = vmlaq_lane_f32(negCoef1.val[0], negCoef.val[0], interp, 0); // rev
+            negCoef.val[1] = vmlaq_lane_f32(negCoef1.val[1], negCoef.val[1], interp, 0); // rev
+        }
+        switch (CHANNELS) {
+        case 1: {
+#ifdef vld1q_f32_x2
+            float32x4x2_t posSamp = vld1q_f32_x2(sP);
+            float32x4x2_t negSamp = vld1q_f32_x2(sN);
+            sN += 8;
+            sP -= 8;
+#else
+            float32x4x2_t posSamp;
+            posSamp.val[0] = vld1q_f32(sP);
+            sP += 4;
+            posSamp.val[1] = vld1q_f32(sP);
+            sP -= 12;
+            float32x4x2_t negSamp;
+            negSamp.val[0] = vld1q_f32(sN);
+            sN += 4;
+            negSamp.val[1] = vld1q_f32(sN);
+            sN += 4;
+#endif
+            // effectively we want a vrev128q_f32()
+            posSamp.val[0] = vrev64q_f32(posSamp.val[0]);
+            posSamp.val[1] = vrev64q_f32(posSamp.val[1]);
+            posSamp.val[0] = vcombine_f32(
+                    vget_high_f32(posSamp.val[0]), vget_low_f32(posSamp.val[0]));
+            posSamp.val[1] = vcombine_f32(
+                    vget_high_f32(posSamp.val[1]), vget_low_f32(posSamp.val[1]));
+
+            accum = vmlaq_f32(accum, posSamp.val[0], posCoef.val[1]);
+            accum = vmlaq_f32(accum, posSamp.val[1], posCoef.val[0]);
+            accum = vmlaq_f32(accum, negSamp.val[0], negCoef.val[0]);
+            accum = vmlaq_f32(accum, negSamp.val[1], negCoef.val[1]);
+        } break;
+        case 2: {
+            float32x4x2_t posSamp0 = vld2q_f32(sP);
+            sP += 8;
+            float32x4x2_t negSamp0 = vld2q_f32(sN);
+            sN += 8;
+            posSamp0.val[0] = vrev64q_f32(posSamp0.val[0]);
+            posSamp0.val[1] = vrev64q_f32(posSamp0.val[1]);
+            posSamp0.val[0] = vcombine_f32(
+                    vget_high_f32(posSamp0.val[0]), vget_low_f32(posSamp0.val[0]));
+            posSamp0.val[1] = vcombine_f32(
+                    vget_high_f32(posSamp0.val[1]), vget_low_f32(posSamp0.val[1]));
+
+            float32x4x2_t posSamp1 = vld2q_f32(sP);
+            sP -= 24;
+            float32x4x2_t negSamp1 = vld2q_f32(sN);
+            sN += 8;
+            posSamp1.val[0] = vrev64q_f32(posSamp1.val[0]);
+            posSamp1.val[1] = vrev64q_f32(posSamp1.val[1]);
+            posSamp1.val[0] = vcombine_f32(
+                    vget_high_f32(posSamp1.val[0]), vget_low_f32(posSamp1.val[0]));
+            posSamp1.val[1] = vcombine_f32(
+                    vget_high_f32(posSamp1.val[1]), vget_low_f32(posSamp1.val[1]));
+
+            // Note: speed is affected by accumulation order.
+            // Also, speed appears slower using vmul/vadd instead of vmla for
+            // stereo case, comparable for mono.
+
+            accum = vmlaq_f32(accum, negSamp0.val[0], negCoef.val[0]);
+            accum = vmlaq_f32(accum, negSamp1.val[0], negCoef.val[1]);
+            accum2 = vmlaq_f32(accum2, negSamp0.val[1], negCoef.val[0]);
+            accum2 = vmlaq_f32(accum2, negSamp1.val[1], negCoef.val[1]);
+
+            accum = vmlaq_f32(accum, posSamp0.val[0], posCoef.val[1]); // reversed
+            accum = vmlaq_f32(accum, posSamp1.val[0], posCoef.val[0]); // reversed
+            accum2 = vmlaq_f32(accum2, posSamp0.val[1], posCoef.val[1]); // reversed
+            accum2 = vmlaq_f32(accum2, posSamp1.val[1], posCoef.val[0]); // reversed
+        } break;
+        }
+    } while (count -= 8);
+
+    // multiply by volume and save
+    volumeLR = (const float*)__builtin_assume_aligned(volumeLR, 8);
+    float32x2_t vLR = vld1_f32(volumeLR);
+    float32x2_t outSamp = vld1_f32(out);
+    // combine and funnel down accumulator
+    float32x2_t outAccum = vpadd_f32(vget_low_f32(accum), vget_high_f32(accum));
+    if (CHANNELS == 1) {
+        // duplicate accum to both L and R
+        outAccum = vpadd_f32(outAccum, outAccum);
+    } else if (CHANNELS == 2) {
+        // accum2 contains R, fold in
+        float32x2_t outAccum2 = vpadd_f32(vget_low_f32(accum2), vget_high_f32(accum2));
+        outAccum = vpadd_f32(outAccum, outAccum2);
+    }
+    outSamp = vmla_f32(outSamp, outAccum, vLR);
+    vst1_f32(out, outSamp);
+}
+
 template <>
 inline void ProcessL<1, 16>(int32_t* const out,
         int count,
@@ -58,6 +531,10 @@
         const int16_t* sN,
         const int32_t* const volumeLR)
 {
+#ifdef USE_INTRINSIC
+    ProcessNeonIntrinsic<1, 16, true>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            0 /*lerpP*/, NULL /*coefsP1*/, NULL /*coefsN1*/);
+#else
     const int CHANNELS = 1; // template specialization does not preserve params
     const int STRIDE = 16;
     sP -= CHANNELS*((STRIDE>>1)-1);
@@ -99,6 +576,7 @@
           "q0", "q1", "q2", "q3",
           "q8", "q10"
     );
+#endif
 }
 
 template <>
@@ -110,6 +588,10 @@
         const int16_t* sN,
         const int32_t* const volumeLR)
 {
+#ifdef USE_INTRINSIC
+    ProcessNeonIntrinsic<2, 16, true>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            0 /*lerpP*/, NULL /*coefsP1*/, NULL /*coefsN1*/);
+#else
     const int CHANNELS = 2; // template specialization does not preserve params
     const int STRIDE = 16;
     sP -= CHANNELS*((STRIDE>>1)-1);
@@ -119,13 +601,13 @@
 
         "1:                                      \n"
 
-        "vld2.16        {q2, q3}, [%[sP]]        \n"// (3+0d) load 8 16-bits stereo samples
-        "vld2.16        {q5, q6}, [%[sN]]!       \n"// (3) load 8 16-bits stereo samples
+        "vld2.16        {q2, q3}, [%[sP]]        \n"// (3+0d) load 8 16-bits stereo frames
+        "vld2.16        {q5, q6}, [%[sN]]!       \n"// (3) load 8 16-bits stereo frames
         "vld1.16        {q8}, [%[coefsP0]:128]!  \n"// (1) load 8 16-bits coefs
         "vld1.16        {q10}, [%[coefsN0]:128]! \n"// (1) load 8 16-bits coefs
 
-        "vrev64.16      q2, q2                   \n"// (1) reverse 8 frames of the left positive
-        "vrev64.16      q3, q3                   \n"// (0 combines+) reverse right positive
+        "vrev64.16      q2, q2                   \n"// (1) reverse 8 samples of positive left
+        "vrev64.16      q3, q3                   \n"// (0 combines+) reverse positive right
 
         "vmlal.s16      q0, d4, d17              \n"// (1) multiply (reversed) samples left
         "vmlal.s16      q0, d5, d16              \n"// (1) multiply (reversed) samples left
@@ -157,6 +639,7 @@
           "q4", "q5", "q6",
           "q8", "q10"
      );
+#endif
 }
 
 template <>
@@ -171,6 +654,11 @@
         uint32_t lerpP,
         const int32_t* const volumeLR)
 {
+#ifdef USE_INTRINSIC
+    ProcessNeonIntrinsic<1, 16, false>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            lerpP, coefsP1, coefsN1);
+#else
+
     const int CHANNELS = 1; // template specialization does not preserve params
     const int STRIDE = 16;
     sP -= CHANNELS*((STRIDE>>1)-1);
@@ -227,6 +715,7 @@
           "q0", "q1", "q2", "q3",
           "q8", "q9", "q10", "q11"
     );
+#endif
 }
 
 template <>
@@ -241,6 +730,10 @@
         uint32_t lerpP,
         const int32_t* const volumeLR)
 {
+#ifdef USE_INTRINSIC
+    ProcessNeonIntrinsic<2, 16, false>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            lerpP, coefsP1, coefsN1);
+#else
     const int CHANNELS = 2; // template specialization does not preserve params
     const int STRIDE = 16;
     sP -= CHANNELS*((STRIDE>>1)-1);
@@ -251,8 +744,8 @@
 
         "1:                                      \n"
 
-        "vld2.16        {q2, q3}, [%[sP]]        \n"// (3+0d) load 8 16-bits stereo samples
-        "vld2.16        {q5, q6}, [%[sN]]!       \n"// (3) load 8 16-bits stereo samples
+        "vld2.16        {q2, q3}, [%[sP]]        \n"// (3+0d) load 8 16-bits stereo frames
+        "vld2.16        {q5, q6}, [%[sN]]!       \n"// (3) load 8 16-bits stereo frames
         "vld1.16        {q8}, [%[coefsP0]:128]!  \n"// (1) load 8 16-bits coefs
         "vld1.16        {q9}, [%[coefsP1]:128]!  \n"// (1) load 8 16-bits coefs for interpolation
         "vld1.16        {q10}, [%[coefsN1]:128]! \n"// (1) load 8 16-bits coefs
@@ -264,8 +757,8 @@
         "vqrdmulh.s16   q9, q9, d2[0]            \n"// (2) interpolate (step2) 1st set of coefs
         "vqrdmulh.s16   q11, q11, d2[0]          \n"// (2) interpolate (step2) 2nd set of coefs
 
-        "vrev64.16      q2, q2                   \n"// (1) reverse 8 frames of the left positive
-        "vrev64.16      q3, q3                   \n"// (1) reverse 8 frames of the right positive
+        "vrev64.16      q2, q2                   \n"// (1) reverse 8 samples of positive left
+        "vrev64.16      q3, q3                   \n"// (1) reverse 8 samples of positive right
 
         "vadd.s16       q8, q8, q9               \n"// (1+1d) interpolate (step3) 1st set
         "vadd.s16       q10, q10, q11            \n"// (1+1d) interpolate (step3) 2nd set
@@ -303,6 +796,7 @@
           "q4", "q5", "q6",
           "q8", "q9", "q10", "q11"
     );
+#endif
 }
 
 template <>
@@ -314,6 +808,10 @@
         const int16_t* sN,
         const int32_t* const volumeLR)
 {
+#ifdef USE_INTRINSIC
+    ProcessNeonIntrinsic<1, 16, true>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            0 /*lerpP*/, NULL /*coefsP1*/, NULL /*coefsN1*/);
+#else
     const int CHANNELS = 1; // template specialization does not preserve params
     const int STRIDE = 16;
     sP -= CHANNELS*((STRIDE>>1)-1);
@@ -327,7 +825,7 @@
         "vld1.32        {q8, q9}, [%[coefsP0]:128]!   \n"// load 8 32-bits coefs
         "vld1.32        {q10, q11}, [%[coefsN0]:128]! \n"// load 8 32-bits coefs
 
-        "vrev64.16      q2, q2                        \n"// reverse 8 frames of the positive side
+        "vrev64.16      q2, q2                        \n"// reverse 8 samples of the positive side
 
         "vshll.s16      q12, d4, #15                  \n"// extend samples to 31 bits
         "vshll.s16      q13, d5, #15                  \n"// extend samples to 31 bits
@@ -335,10 +833,10 @@
         "vshll.s16      q14, d6, #15                  \n"// extend samples to 31 bits
         "vshll.s16      q15, d7, #15                  \n"// extend samples to 31 bits
 
-        "vqrdmulh.s32   q12, q12, q9                  \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q13, q13, q8                  \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q14, q14, q10                 \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q15, q15, q11                 \n"// multiply samples by interpolated coef
+        "vqrdmulh.s32   q12, q12, q9                  \n"// multiply samples
+        "vqrdmulh.s32   q13, q13, q8                  \n"// multiply samples
+        "vqrdmulh.s32   q14, q14, q10                 \n"// multiply samples
+        "vqrdmulh.s32   q15, q15, q11                 \n"// multiply samples
 
         "vadd.s32       q0, q0, q12                   \n"// accumulate result
         "vadd.s32       q13, q13, q14                 \n"// accumulate result
@@ -364,6 +862,7 @@
           "q8", "q9", "q10", "q11",
           "q12", "q13", "q14", "q15"
     );
+#endif
 }
 
 template <>
@@ -375,6 +874,10 @@
         const int16_t* sN,
         const int32_t* const volumeLR)
 {
+#ifdef USE_INTRINSIC
+    ProcessNeonIntrinsic<2, 16, true>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            0 /*lerpP*/, NULL /*coefsP1*/, NULL /*coefsN1*/);
+#else
     const int CHANNELS = 2; // template specialization does not preserve params
     const int STRIDE = 16;
     sP -= CHANNELS*((STRIDE>>1)-1);
@@ -384,13 +887,13 @@
 
         "1:                                           \n"
 
-        "vld2.16        {q2, q3}, [%[sP]]             \n"// load 4 16-bits stereo samples
-        "vld2.16        {q5, q6}, [%[sN]]!            \n"// load 4 16-bits stereo samples
-        "vld1.32        {q8, q9}, [%[coefsP0]:128]!   \n"// load 4 32-bits coefs
-        "vld1.32        {q10, q11}, [%[coefsN0]:128]! \n"// load 4 32-bits coefs
+        "vld2.16        {q2, q3}, [%[sP]]             \n"// load 8 16-bits stereo frames
+        "vld2.16        {q5, q6}, [%[sN]]!            \n"// load 8 16-bits stereo frames
+        "vld1.32        {q8, q9}, [%[coefsP0]:128]!   \n"// load 8 32-bits coefs
+        "vld1.32        {q10, q11}, [%[coefsN0]:128]! \n"// load 8 32-bits coefs
 
-        "vrev64.16      q2, q2                        \n"// reverse 8 frames of the positive side
-        "vrev64.16      q3, q3                        \n"// reverse 8 frames of the positive side
+        "vrev64.16      q2, q2                        \n"// reverse 8 samples of positive left
+        "vrev64.16      q3, q3                        \n"// reverse 8 samples of positive right
 
         "vshll.s16      q12,  d4, #15                 \n"// extend samples to 31 bits
         "vshll.s16      q13,  d5, #15                 \n"// extend samples to 31 bits
@@ -398,15 +901,15 @@
         "vshll.s16      q14,  d10, #15                \n"// extend samples to 31 bits
         "vshll.s16      q15,  d11, #15                \n"// extend samples to 31 bits
 
-        "vqrdmulh.s32   q12, q12, q9                  \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q13, q13, q8                  \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q14, q14, q10                 \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q15, q15, q11                 \n"// multiply samples by interpolated coef
+        "vqrdmulh.s32   q12, q12, q9                  \n"// multiply samples by coef
+        "vqrdmulh.s32   q13, q13, q8                  \n"// multiply samples by coef
+        "vqrdmulh.s32   q14, q14, q10                 \n"// multiply samples by coef
+        "vqrdmulh.s32   q15, q15, q11                 \n"// multiply samples by coef
 
         "vadd.s32       q0, q0, q12                   \n"// accumulate result
         "vadd.s32       q13, q13, q14                 \n"// accumulate result
-        "vadd.s32       q0, q0, q15                   \n"// (+1) accumulate result
-        "vadd.s32       q0, q0, q13                   \n"// (+1) accumulate result
+        "vadd.s32       q0, q0, q15                   \n"// accumulate result
+        "vadd.s32       q0, q0, q13                   \n"// accumulate result
 
         "vshll.s16      q12,  d6, #15                 \n"// extend samples to 31 bits
         "vshll.s16      q13,  d7, #15                 \n"// extend samples to 31 bits
@@ -414,15 +917,15 @@
         "vshll.s16      q14,  d12, #15                \n"// extend samples to 31 bits
         "vshll.s16      q15,  d13, #15                \n"// extend samples to 31 bits
 
-        "vqrdmulh.s32   q12, q12, q9                  \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q13, q13, q8                  \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q14, q14, q10                 \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q15, q15, q11                 \n"// multiply samples by interpolated coef
+        "vqrdmulh.s32   q12, q12, q9                  \n"// multiply samples by coef
+        "vqrdmulh.s32   q13, q13, q8                  \n"// multiply samples by coef
+        "vqrdmulh.s32   q14, q14, q10                 \n"// multiply samples by coef
+        "vqrdmulh.s32   q15, q15, q11                 \n"// multiply samples by coef
 
         "vadd.s32       q4, q4, q12                   \n"// accumulate result
         "vadd.s32       q13, q13, q14                 \n"// accumulate result
-        "vadd.s32       q4, q4, q15                   \n"// (+1) accumulate result
-        "vadd.s32       q4, q4, q13                   \n"// (+1) accumulate result
+        "vadd.s32       q4, q4, q15                   \n"// accumulate result
+        "vadd.s32       q4, q4, q13                   \n"// accumulate result
 
         "subs           %[count], %[count], #8        \n"// update loop counter
         "sub            %[sP], %[sP], #32             \n"// move pointer to next set of samples
@@ -444,6 +947,7 @@
           "q8", "q9", "q10", "q11",
           "q12", "q13", "q14", "q15"
     );
+#endif
 }
 
 template <>
@@ -458,6 +962,10 @@
         uint32_t lerpP,
         const int32_t* const volumeLR)
 {
+#ifdef USE_INTRINSIC
+    ProcessNeonIntrinsic<1, 16, false>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            lerpP, coefsP1, coefsN1);
+#else
     const int CHANNELS = 1; // template specialization does not preserve params
     const int STRIDE = 16;
     sP -= CHANNELS*((STRIDE>>1)-1);
@@ -489,7 +997,7 @@
         "vadd.s32       q10, q10, q14                 \n"// interpolate (step3)
         "vadd.s32       q11, q11, q15                 \n"// interpolate (step3)
 
-        "vrev64.16      q2, q2                        \n"// reverse 8 frames of the positive side
+        "vrev64.16      q2, q2                        \n"// reverse 8 samples of the positive side
 
         "vshll.s16      q12,  d4, #15                 \n"// extend samples to 31 bits
         "vshll.s16      q13,  d5, #15                 \n"// extend samples to 31 bits
@@ -529,6 +1037,7 @@
           "q8", "q9", "q10", "q11",
           "q12", "q13", "q14", "q15"
     );
+#endif
 }
 
 template <>
@@ -543,6 +1052,10 @@
         uint32_t lerpP,
         const int32_t* const volumeLR)
 {
+#ifdef USE_INTRINSIC
+    ProcessNeonIntrinsic<2, 16, false>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            lerpP, coefsP1, coefsN1);
+#else
     const int CHANNELS = 2; // template specialization does not preserve params
     const int STRIDE = 16;
     sP -= CHANNELS*((STRIDE>>1)-1);
@@ -553,8 +1066,8 @@
 
         "1:                                           \n"
 
-        "vld2.16        {q2, q3}, [%[sP]]             \n"// load 4 16-bits stereo samples
-        "vld2.16        {q5, q6}, [%[sN]]!            \n"// load 4 16-bits stereo samples
+        "vld2.16        {q2, q3}, [%[sP]]             \n"// load 8 16-bits stereo frames
+        "vld2.16        {q5, q6}, [%[sN]]!            \n"// load 8 16-bits stereo frames
         "vld1.32        {q8, q9}, [%[coefsP0]:128]!   \n"// load 8 32-bits coefs
         "vld1.32        {q12, q13}, [%[coefsP1]:128]! \n"// load 8 32-bits coefs
         "vld1.32        {q10, q11}, [%[coefsN1]:128]! \n"// load 8 32-bits coefs
@@ -575,8 +1088,8 @@
         "vadd.s32       q10, q10, q14                 \n"// interpolate (step3)
         "vadd.s32       q11, q11, q15                 \n"// interpolate (step3)
 
-        "vrev64.16      q2, q2                        \n"// reverse 8 frames of the positive side
-        "vrev64.16      q3, q3                        \n"// reverse 8 frames of the positive side
+        "vrev64.16      q2, q2                        \n"// reverse 8 samples of positive left
+        "vrev64.16      q3, q3                        \n"// reverse 8 samples of positive right
 
         "vshll.s16      q12,  d4, #15                 \n"// extend samples to 31 bits
         "vshll.s16      q13,  d5, #15                 \n"// extend samples to 31 bits
@@ -591,8 +1104,8 @@
 
         "vadd.s32       q0, q0, q12                   \n"// accumulate result
         "vadd.s32       q13, q13, q14                 \n"// accumulate result
-        "vadd.s32       q0, q0, q15                   \n"// (+1) accumulate result
-        "vadd.s32       q0, q0, q13                   \n"// (+1) accumulate result
+        "vadd.s32       q0, q0, q15                   \n"// accumulate result
+        "vadd.s32       q0, q0, q13                   \n"// accumulate result
 
         "vshll.s16      q12,  d6, #15                 \n"// extend samples to 31 bits
         "vshll.s16      q13,  d7, #15                 \n"// extend samples to 31 bits
@@ -607,8 +1120,8 @@
 
         "vadd.s32       q4, q4, q12                   \n"// accumulate result
         "vadd.s32       q13, q13, q14                 \n"// accumulate result
-        "vadd.s32       q4, q4, q15                   \n"// (+1) accumulate result
-        "vadd.s32       q4, q4, q13                   \n"// (+1) accumulate result
+        "vadd.s32       q4, q4, q15                   \n"// accumulate result
+        "vadd.s32       q4, q4, q13                   \n"// accumulate result
 
         "subs           %[count], %[count], #8        \n"// update loop counter
         "sub            %[sP], %[sP], #32             \n"// move pointer to next set of samples
@@ -633,517 +1146,69 @@
           "q8", "q9", "q10", "q11",
           "q12", "q13", "q14", "q15"
     );
+#endif
 }
 
-template <>
-inline void ProcessL<1, 8>(int32_t* const out,
+template<>
+inline void ProcessL<1, 16>(float* const out,
         int count,
-        const int16_t* coefsP,
-        const int16_t* coefsN,
-        const int16_t* sP,
-        const int16_t* sN,
-        const int32_t* const volumeLR)
+        const float* coefsP,
+        const float* coefsN,
+        const float* sP,
+        const float* sN,
+        const float* const volumeLR)
 {
-    const int CHANNELS = 1; // template specialization does not preserve params
-    const int STRIDE = 8;
-    sP -= CHANNELS*((STRIDE>>1)-1);
-    asm (
-        "veor           q0, q0, q0               \n"// (0 - combines+) accumulator = 0
-
-        "1:                                      \n"
-
-        "vld1.16        {d4}, [%[sP]]            \n"// (2+0d) load 4 16-bits mono samples
-        "vld1.16        {d6}, [%[sN]]!           \n"// (2) load 4 16-bits mono samples
-        "vld1.16        {d16}, [%[coefsP0]:64]!  \n"// (1) load 4 16-bits coefs
-        "vld1.16        {d20}, [%[coefsN0]:64]!  \n"// (1) load 4 16-bits coefs
-
-        "vrev64.16      d4, d4                   \n"// (1) reversed s3, s2, s1, s0, s7, s6, s5, s4
-
-        // reordering the vmal to do d6, d7 before d4, d5 is slower(?)
-        "vmlal.s16      q0, d4, d16              \n"// (1) multiply (reversed)samples by coef
-        "vmlal.s16      q0, d6, d20              \n"// (1) multiply neg samples
-
-        // moving these ARM instructions before neon above seems to be slower
-        "subs           %[count], %[count], #4   \n"// (1) update loop counter
-        "sub            %[sP], %[sP], #8         \n"// (0) move pointer to next set of samples
-
-        // sP used after branch (warning)
-        "bne            1b                       \n"// loop
-
-        ASSEMBLY_ACCUMULATE_MONO
-
-        : [out]     "=Uv" (out[0]),
-          [count]   "+r" (count),
-          [coefsP0] "+r" (coefsP),
-          [coefsN0] "+r" (coefsN),
-          [sP]      "+r" (sP),
-          [sN]      "+r" (sN)
-        : [vLR]     "r" (volumeLR)
-        : "cc", "memory",
-          "q0", "q1", "q2", "q3",
-          "q8", "q10"
-    );
+    ProcessNeonIntrinsic<1, 16, true>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            0 /*lerpP*/, NULL /*coefsP1*/, NULL /*coefsN1*/);
 }
 
-template <>
-inline void ProcessL<2, 8>(int32_t* const out,
+template<>
+inline void ProcessL<2, 16>(float* const out,
         int count,
-        const int16_t* coefsP,
-        const int16_t* coefsN,
-        const int16_t* sP,
-        const int16_t* sN,
-        const int32_t* const volumeLR)
+        const float* coefsP,
+        const float* coefsN,
+        const float* sP,
+        const float* sN,
+        const float* const volumeLR)
 {
-    const int CHANNELS = 2; // template specialization does not preserve params
-    const int STRIDE = 8;
-    sP -= CHANNELS*((STRIDE>>1)-1);
-    asm (
-        "veor           q0, q0, q0               \n"// (1) acc_L = 0
-        "veor           q4, q4, q4               \n"// (0 combines+) acc_R = 0
-
-        "1:                                      \n"
-
-        "vld2.16        {d4, d5}, [%[sP]]        \n"// (2+0d) load 8 16-bits stereo samples
-        "vld2.16        {d6, d7}, [%[sN]]!       \n"// (2) load 8 16-bits stereo samples
-        "vld1.16        {d16}, [%[coefsP0]:64]!  \n"// (1) load 8 16-bits coefs
-        "vld1.16        {d20}, [%[coefsN0]:64]!  \n"// (1) load 8 16-bits coefs
-
-        "vrev64.16      q2, q2                   \n"// (1) reverse 8 frames of the left positive
-
-        "vmlal.s16      q0, d4, d16              \n"// (1) multiply (reversed) samples left
-        "vmlal.s16      q4, d5, d16              \n"// (1) multiply (reversed) samples right
-        "vmlal.s16      q0, d6, d20              \n"// (1) multiply samples left
-        "vmlal.s16      q4, d7, d20              \n"// (1) multiply samples right
-
-        // moving these ARM before neon seems to be slower
-        "subs           %[count], %[count], #4   \n"// (1) update loop counter
-        "sub            %[sP], %[sP], #16        \n"// (0) move pointer to next set of samples
-
-        // sP used after branch (warning)
-        "bne            1b                       \n"// loop
-
-        ASSEMBLY_ACCUMULATE_STEREO
-
-        : [out] "=Uv" (out[0]),
-          [count] "+r" (count),
-          [coefsP0] "+r" (coefsP),
-          [coefsN0] "+r" (coefsN),
-          [sP] "+r" (sP),
-          [sN] "+r" (sN)
-        : [vLR] "r" (volumeLR)
-        : "cc", "memory",
-          "q0", "q1", "q2", "q3",
-          "q4", "q5", "q6",
-          "q8", "q10"
-     );
+    ProcessNeonIntrinsic<2, 16, true>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            0 /*lerpP*/, NULL /*coefsP1*/, NULL /*coefsN1*/);
 }
 
-template <>
-inline void Process<1, 8>(int32_t* const out,
+template<>
+inline void Process<1, 16>(float* const out,
         int count,
-        const int16_t* coefsP,
-        const int16_t* coefsN,
-        const int16_t* coefsP1,
-        const int16_t* coefsN1,
-        const int16_t* sP,
-        const int16_t* sN,
-        uint32_t lerpP,
-        const int32_t* const volumeLR)
+        const float* coefsP,
+        const float* coefsN,
+        const float* coefsP1,
+        const float* coefsN1,
+        const float* sP,
+        const float* sN,
+        float lerpP,
+        const float* const volumeLR)
 {
-    const int CHANNELS = 1; // template specialization does not preserve params
-    const int STRIDE = 8;
-    sP -= CHANNELS*((STRIDE>>1)-1);
-    asm (
-        "vmov.32        d2[0], %[lerpP]          \n"// load the positive phase S32 Q15
-        "veor           q0, q0, q0               \n"// (0 - combines+) accumulator = 0
-
-        "1:                                      \n"
-
-        "vld1.16        {d4}, [%[sP]]            \n"// (2+0d) load 4 16-bits mono samples
-        "vld1.16        {d6}, [%[sN]]!           \n"// (2) load 4 16-bits mono samples
-        "vld1.16        {d16}, [%[coefsP0]:64]!  \n"// (1) load 4 16-bits coefs
-        "vld1.16        {d17}, [%[coefsP1]:64]!  \n"// (1) load 4 16-bits coefs for interpolation
-        "vld1.16        {d20}, [%[coefsN1]:64]!  \n"// (1) load 4 16-bits coefs
-        "vld1.16        {d21}, [%[coefsN0]:64]!  \n"// (1) load 4 16-bits coefs for interpolation
-
-        "vsub.s16       d17, d17, d16            \n"// (1) interpolate (step1) 1st set of coefs
-        "vsub.s16       d21, d21, d20            \n"// (1) interpolate (step1) 2nd set of coets
-
-        "vqrdmulh.s16   d17, d17, d2[0]          \n"// (2) interpolate (step2) 1st set of coefs
-        "vqrdmulh.s16   d21, d21, d2[0]          \n"// (2) interpolate (step2) 2nd set of coefs
-
-        "vrev64.16      d4, d4                   \n"// (1) reverse s3, s2, s1, s0, s7, s6, s5, s4
-
-        "vadd.s16       d16, d16, d17            \n"// (1+2d) interpolate (step3) 1st set
-        "vadd.s16       d20, d20, d21            \n"// (1+1d) interpolate (step3) 2nd set
-
-        // reordering the vmal to do d6, d7 before d4, d5 is slower(?)
-        "vmlal.s16      q0, d4, d16              \n"// (1+0d) multiply (reversed)by coef
-        "vmlal.s16      q0, d6, d20              \n"// (1) multiply neg samples
-
-        // moving these ARM instructions before neon above seems to be slower
-        "subs           %[count], %[count], #4   \n"// (1) update loop counter
-        "sub            %[sP], %[sP], #8        \n"// move pointer to next set of samples
-
-        // sP used after branch (warning)
-        "bne            1b                       \n"// loop
-
-        ASSEMBLY_ACCUMULATE_MONO
-
-        : [out]     "=Uv" (out[0]),
-          [count]   "+r" (count),
-          [coefsP0] "+r" (coefsP),
-          [coefsN0] "+r" (coefsN),
-          [coefsP1] "+r" (coefsP1),
-          [coefsN1] "+r" (coefsN1),
-          [sP]      "+r" (sP),
-          [sN]      "+r" (sN)
-        : [lerpP]   "r" (lerpP),
-          [vLR]     "r" (volumeLR)
-        : "cc", "memory",
-          "q0", "q1", "q2", "q3",
-          "q8", "q9", "q10", "q11"
-    );
+    ProcessNeonIntrinsic<1, 16, false>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            lerpP, coefsP1, coefsN1);
 }
 
-template <>
-inline void Process<2, 8>(int32_t* const out,
+template<>
+inline void Process<2, 16>(float* const out,
         int count,
-        const int16_t* coefsP,
-        const int16_t* coefsN,
-        const int16_t* coefsP1,
-        const int16_t* coefsN1,
-        const int16_t* sP,
-        const int16_t* sN,
-        uint32_t lerpP,
-        const int32_t* const volumeLR)
+        const float* coefsP,
+        const float* coefsN,
+        const float* coefsP1,
+        const float* coefsN1,
+        const float* sP,
+        const float* sN,
+        float lerpP,
+        const float* const volumeLR)
 {
-    const int CHANNELS = 2; // template specialization does not preserve params
-    const int STRIDE = 8;
-    sP -= CHANNELS*((STRIDE>>1)-1);
-    asm (
-        "vmov.32        d2[0], %[lerpP]          \n"// load the positive phase
-        "veor           q0, q0, q0               \n"// (1) acc_L = 0
-        "veor           q4, q4, q4               \n"// (0 combines+) acc_R = 0
-
-        "1:                                      \n"
-
-        "vld2.16        {d4, d5}, [%[sP]]        \n"// (3+0d) load 8 16-bits stereo samples
-        "vld2.16        {d6, d7}, [%[sN]]!       \n"// (3) load 8 16-bits stereo samples
-        "vld1.16        {d16}, [%[coefsP0]:64]!  \n"// (1) load 8 16-bits coefs
-        "vld1.16        {d17}, [%[coefsP1]:64]!  \n"// (1) load 8 16-bits coefs for interpolation
-        "vld1.16        {d20}, [%[coefsN1]:64]!  \n"// (1) load 8 16-bits coefs
-        "vld1.16        {d21}, [%[coefsN0]:64]!  \n"// (1) load 8 16-bits coefs for interpolation
-
-        "vsub.s16       d17, d17, d16            \n"// (1) interpolate (step1) 1st set of coefs
-        "vsub.s16       d21, d21, d20            \n"// (1) interpolate (step1) 2nd set of coets
-
-        "vqrdmulh.s16   d17, d17, d2[0]          \n"// (2) interpolate (step2) 1st set of coefs
-        "vqrdmulh.s16   d21, d21, d2[0]          \n"// (2) interpolate (step2) 2nd set of coefs
-
-        "vrev64.16      q2, q2                   \n"// (1) reverse 8 frames of the left positive
-
-        "vadd.s16       d16, d16, d17            \n"// (1+1d) interpolate (step3) 1st set
-        "vadd.s16       d20, d20, d21            \n"// (1+1d) interpolate (step3) 2nd set
-
-        "vmlal.s16      q0, d4, d16              \n"// (1) multiply (reversed) samples left
-        "vmlal.s16      q4, d5, d16              \n"// (1) multiply (reversed) samples right
-        "vmlal.s16      q0, d6, d20              \n"// (1) multiply samples left
-        "vmlal.s16      q4, d7, d20              \n"// (1) multiply samples right
-
-        // moving these ARM before neon seems to be slower
-        "subs           %[count], %[count], #4   \n"// (1) update loop counter
-        "sub            %[sP], %[sP], #16        \n"// move pointer to next set of samples
-
-        // sP used after branch (warning)
-        "bne            1b                       \n"// loop
-
-        ASSEMBLY_ACCUMULATE_STEREO
-
-        : [out] "=Uv" (out[0]),
-          [count] "+r" (count),
-          [coefsP0] "+r" (coefsP),
-          [coefsN0] "+r" (coefsN),
-          [coefsP1] "+r" (coefsP1),
-          [coefsN1] "+r" (coefsN1),
-          [sP] "+r" (sP),
-          [sN] "+r" (sN)
-        : [lerpP]   "r" (lerpP),
-          [vLR] "r" (volumeLR)
-        : "cc", "memory",
-          "q0", "q1", "q2", "q3",
-          "q4", "q5", "q6",
-          "q8", "q9", "q10", "q11"
-    );
-}
-
-template <>
-inline void ProcessL<1, 8>(int32_t* const out,
-        int count,
-        const int32_t* coefsP,
-        const int32_t* coefsN,
-        const int16_t* sP,
-        const int16_t* sN,
-        const int32_t* const volumeLR)
-{
-    const int CHANNELS = 1; // template specialization does not preserve params
-    const int STRIDE = 8;
-    sP -= CHANNELS*((STRIDE>>1)-1);
-    asm (
-        "veor           q0, q0, q0               \n"// result, initialize to 0
-
-        "1:                                      \n"
-
-        "vld1.16        {d4}, [%[sP]]            \n"// load 4 16-bits mono samples
-        "vld1.16        {d6}, [%[sN]]!           \n"// load 4 16-bits mono samples
-        "vld1.32        {q8}, [%[coefsP0]:128]!  \n"// load 4 32-bits coefs
-        "vld1.32        {q10}, [%[coefsN0]:128]! \n"// load 4 32-bits coefs
-
-        "vrev64.16      d4, d4                   \n"// reverse 2 frames of the positive side
-
-        "vshll.s16      q12, d4, #15             \n"// (stall) extend samples to 31 bits
-        "vshll.s16      q14, d6, #15             \n"// extend samples to 31 bits
-
-        "vqrdmulh.s32   q12, q12, q8             \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q14, q14, q10            \n"// multiply samples by interpolated coef
-
-        "vadd.s32       q0, q0, q12              \n"// accumulate result
-        "vadd.s32       q0, q0, q14              \n"// (stall) accumulate result
-
-        "subs           %[count], %[count], #4   \n"// update loop counter
-        "sub            %[sP], %[sP], #8         \n"// move pointer to next set of samples
-
-        "bne            1b                       \n"// loop
-
-        ASSEMBLY_ACCUMULATE_MONO
-
-        : [out] "=Uv" (out[0]),
-          [count] "+r" (count),
-          [coefsP0] "+r" (coefsP),
-          [coefsN0] "+r" (coefsN),
-          [sP] "+r" (sP),
-          [sN] "+r" (sN)
-        : [vLR] "r" (volumeLR)
-        : "cc", "memory",
-          "q0", "q1", "q2", "q3",
-          "q8", "q9", "q10", "q11",
-          "q12", "q14"
-    );
-}
-
-template <>
-inline void ProcessL<2, 8>(int32_t* const out,
-        int count,
-        const int32_t* coefsP,
-        const int32_t* coefsN,
-        const int16_t* sP,
-        const int16_t* sN,
-        const int32_t* const volumeLR)
-{
-    const int CHANNELS = 2; // template specialization does not preserve params
-    const int STRIDE = 8;
-    sP -= CHANNELS*((STRIDE>>1)-1);
-    asm (
-        "veor           q0, q0, q0               \n"// result, initialize to 0
-        "veor           q4, q4, q4               \n"// result, initialize to 0
-
-        "1:                                      \n"
-
-        "vld2.16        {d4, d5}, [%[sP]]        \n"// load 4 16-bits stereo samples
-        "vld2.16        {d6, d7}, [%[sN]]!       \n"// load 4 16-bits stereo samples
-        "vld1.32        {q8}, [%[coefsP0]:128]!  \n"// load 4 32-bits coefs
-        "vld1.32        {q10}, [%[coefsN0]:128]! \n"// load 4 32-bits coefs
-
-        "vrev64.16      q2, q2                   \n"// reverse 2 frames of the positive side
-
-        "vshll.s16      q12, d4, #15             \n"// extend samples to 31 bits
-        "vshll.s16      q13, d5, #15             \n"// extend samples to 31 bits
-
-        "vshll.s16      q14, d6, #15             \n"// extend samples to 31 bits
-        "vshll.s16      q15, d7, #15             \n"// extend samples to 31 bits
-
-        "vqrdmulh.s32   q12, q12, q8             \n"// multiply samples by coef
-        "vqrdmulh.s32   q13, q13, q8             \n"// multiply samples by coef
-        "vqrdmulh.s32   q14, q14, q10            \n"// multiply samples by coef
-        "vqrdmulh.s32   q15, q15, q10            \n"// multiply samples by coef
-
-        "vadd.s32       q0, q0, q12              \n"// accumulate result
-        "vadd.s32       q4, q4, q13              \n"// accumulate result
-        "vadd.s32       q0, q0, q14              \n"// accumulate result
-        "vadd.s32       q4, q4, q15              \n"// accumulate result
-
-        "subs           %[count], %[count], #4   \n"// update loop counter
-        "sub            %[sP], %[sP], #16        \n"// move pointer to next set of samples
-
-        "bne            1b                       \n"// loop
-
-        ASSEMBLY_ACCUMULATE_STEREO
-
-        : [out]     "=Uv" (out[0]),
-          [count]   "+r" (count),
-          [coefsP0] "+r" (coefsP),
-          [coefsN0] "+r" (coefsN),
-          [sP]      "+r" (sP),
-          [sN]      "+r" (sN)
-        : [vLR]     "r" (volumeLR)
-        : "cc", "memory",
-          "q0", "q1", "q2", "q3", "q4",
-          "q8", "q9", "q10", "q11",
-          "q12", "q13", "q14", "q15"
-    );
-}
-
-template <>
-inline void Process<1, 8>(int32_t* const out,
-        int count,
-        const int32_t* coefsP,
-        const int32_t* coefsN,
-        const int32_t* coefsP1,
-        const int32_t* coefsN1,
-        const int16_t* sP,
-        const int16_t* sN,
-        uint32_t lerpP,
-        const int32_t* const volumeLR)
-{
-    const int CHANNELS = 1; // template specialization does not preserve params
-    const int STRIDE = 8;
-    sP -= CHANNELS*((STRIDE>>1)-1);
-    asm (
-        "vmov.32        d2[0], %[lerpP]          \n"// load the positive phase
-        "veor           q0, q0, q0               \n"// result, initialize to 0
-
-        "1:                                      \n"
-
-        "vld1.16        {d4}, [%[sP]]            \n"// load 4 16-bits mono samples
-        "vld1.16        {d6}, [%[sN]]!           \n"// load 4 16-bits mono samples
-        "vld1.32        {q8}, [%[coefsP0]:128]!  \n"// load 4 32-bits coefs
-        "vld1.32        {q9}, [%[coefsP1]:128]!  \n"// load 4 32-bits coefs for interpolation
-        "vld1.32        {q10}, [%[coefsN1]:128]! \n"// load 4 32-bits coefs
-        "vld1.32        {q11}, [%[coefsN0]:128]! \n"// load 4 32-bits coefs for interpolation
-
-        "vrev64.16      d4, d4                   \n"// reverse 2 frames of the positive side
-
-        "vsub.s32       q9, q9, q8               \n"// interpolate (step1) 1st set of coefs
-        "vsub.s32       q11, q11, q10            \n"// interpolate (step1) 2nd set of coets
-        "vshll.s16      q12, d4, #15             \n"// extend samples to 31 bits
-
-        "vqrdmulh.s32   q9, q9, d2[0]            \n"// interpolate (step2) 1st set of coefs
-        "vqrdmulh.s32   q11, q11, d2[0]          \n"// interpolate (step2) 2nd set of coefs
-        "vshll.s16      q14, d6, #15             \n"// extend samples to 31 bits
-
-        "vadd.s32       q8, q8, q9               \n"// interpolate (step3) 1st set
-        "vadd.s32       q10, q10, q11            \n"// interpolate (step4) 2nd set
-
-        "vqrdmulh.s32   q12, q12, q8             \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q14, q14, q10            \n"// multiply samples by interpolated coef
-
-        "vadd.s32       q0, q0, q12              \n"// accumulate result
-        "vadd.s32       q0, q0, q14              \n"// accumulate result
-
-        "subs           %[count], %[count], #4   \n"// update loop counter
-        "sub            %[sP], %[sP], #8         \n"// move pointer to next set of samples
-
-        "bne            1b                       \n"// loop
-
-        ASSEMBLY_ACCUMULATE_MONO
-
-        : [out]     "=Uv" (out[0]),
-          [count]   "+r" (count),
-          [coefsP0] "+r" (coefsP),
-          [coefsP1] "+r" (coefsP1),
-          [coefsN0] "+r" (coefsN),
-          [coefsN1] "+r" (coefsN1),
-          [sP]      "+r" (sP),
-          [sN]      "+r" (sN)
-        : [lerpP]   "r" (lerpP),
-          [vLR]     "r" (volumeLR)
-        : "cc", "memory",
-          "q0", "q1", "q2", "q3",
-          "q8", "q9", "q10", "q11",
-          "q12", "q14"
-    );
-}
-
-template <>
-inline
-void Process<2, 8>(int32_t* const out,
-        int count,
-        const int32_t* coefsP,
-        const int32_t* coefsN,
-        const int32_t* coefsP1,
-        const int32_t* coefsN1,
-        const int16_t* sP,
-        const int16_t* sN,
-        uint32_t lerpP,
-        const int32_t* const volumeLR)
-{
-    const int CHANNELS = 2; // template specialization does not preserve params
-    const int STRIDE = 8;
-    sP -= CHANNELS*((STRIDE>>1)-1);
-    asm (
-        "vmov.32        d2[0], %[lerpP]          \n"// load the positive phase
-        "veor           q0, q0, q0               \n"// result, initialize to 0
-        "veor           q4, q4, q4               \n"// result, initialize to 0
-
-        "1:                                      \n"
-        "vld2.16        {d4, d5}, [%[sP]]        \n"// load 4 16-bits stereo samples
-        "vld2.16        {d6, d7}, [%[sN]]!       \n"// load 4 16-bits stereo samples
-        "vld1.32        {q8}, [%[coefsP0]:128]!  \n"// load 4 32-bits coefs
-        "vld1.32        {q9}, [%[coefsP1]:128]!  \n"// load 4 32-bits coefs for interpolation
-        "vld1.32        {q10}, [%[coefsN1]:128]! \n"// load 4 32-bits coefs
-        "vld1.32        {q11}, [%[coefsN0]:128]! \n"// load 4 32-bits coefs for interpolation
-
-        "vrev64.16      q2, q2                   \n"// (reversed) 2 frames of the positive side
-
-        "vsub.s32       q9, q9, q8               \n"// interpolate (step1) 1st set of coefs
-        "vsub.s32       q11, q11, q10            \n"// interpolate (step1) 2nd set of coets
-        "vshll.s16      q12, d4, #15             \n"// extend samples to 31 bits
-        "vshll.s16      q13, d5, #15             \n"// extend samples to 31 bits
-
-        "vqrdmulh.s32   q9, q9, d2[0]            \n"// interpolate (step2) 1st set of coefs
-        "vqrdmulh.s32   q11, q11, d2[1]          \n"// interpolate (step3) 2nd set of coefs
-        "vshll.s16      q14, d6, #15             \n"// extend samples to 31 bits
-        "vshll.s16      q15, d7, #15             \n"// extend samples to 31 bits
-
-        "vadd.s32       q8, q8, q9               \n"// interpolate (step3) 1st set
-        "vadd.s32       q10, q10, q11            \n"// interpolate (step4) 2nd set
-
-        "vqrdmulh.s32   q12, q12, q8             \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q13, q13, q8             \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q14, q14, q10            \n"// multiply samples by interpolated coef
-        "vqrdmulh.s32   q15, q15, q10            \n"// multiply samples by interpolated coef
-
-        "vadd.s32       q0, q0, q12              \n"// accumulate result
-        "vadd.s32       q4, q4, q13              \n"// accumulate result
-        "vadd.s32       q0, q0, q14              \n"// accumulate result
-        "vadd.s32       q4, q4, q15              \n"// accumulate result
-
-        "subs           %[count], %[count], #4   \n"// update loop counter
-        "sub            %[sP], %[sP], #16        \n"// move pointer to next set of samples
-
-        "bne            1b                       \n"// loop
-
-        ASSEMBLY_ACCUMULATE_STEREO
-
-        : [out]     "=Uv" (out[0]),
-          [count]   "+r" (count),
-          [coefsP0] "+r" (coefsP),
-          [coefsP1] "+r" (coefsP1),
-          [coefsN0] "+r" (coefsN),
-          [coefsN1] "+r" (coefsN1),
-          [sP]      "+r" (sP),
-          [sN]      "+r" (sN)
-        : [lerpP]   "r" (lerpP),
-          [vLR]     "r" (volumeLR)
-        : "cc", "memory",
-          "q0", "q1", "q2", "q3", "q4",
-          "q8", "q9", "q10", "q11",
-          "q12", "q13", "q14", "q15"
-    );
+    ProcessNeonIntrinsic<2, 16, false>(out, count, coefsP, coefsN, sP, sN, volumeLR,
+            lerpP, coefsP1, coefsN1);
 }
 
 #endif //USE_NEON
 
-}; // namespace android
+} // namespace android
 
 #endif /*ANDROID_AUDIO_RESAMPLER_FIR_PROCESS_NEON_H*/
diff --git a/services/audioflinger/AudioResamplerSinc.cpp b/services/audioflinger/AudioResamplerSinc.cpp
index e6fb76c..ba9a356 100644
--- a/services/audioflinger/AudioResamplerSinc.cpp
+++ b/services/audioflinger/AudioResamplerSinc.cpp
@@ -61,135 +61,7 @@
  * cmd-line: fir -l 7 -s 48000 -c 20478
  */
 const uint32_t AudioResamplerSinc::mFirCoefsUp[] __attribute__ ((aligned (32))) = {
-        0x6d374bc7, 0x111c6ba0, 0xf3240e61, 0x07d14a38, 0xfc509e64, 0x0139cee9, 0xffc8c866, 0xfffcc300,
-        0x6d35278a, 0x103e8192, 0xf36b9dfd, 0x07bdfaa5, 0xfc5102d0, 0x013d618d, 0xffc663b9, 0xfffd9592,
-        0x6d2ebafe, 0x0f62811a, 0xf3b3d8ac, 0x07a9f399, 0xfc51d9a6, 0x0140bea5, 0xffc41212, 0xfffe631e,
-        0x6d24069d, 0x0e8875ad, 0xf3fcb43e, 0x07953976, 0xfc53216f, 0x0143e67c, 0xffc1d373, 0xffff2b9f,
-        0x6d150b35, 0x0db06a89, 0xf4462690, 0x077fd0ac, 0xfc54d8ae, 0x0146d965, 0xffbfa7d9, 0xffffef10,
-        0x6d01c9e3, 0x0cda6ab5, 0xf4902587, 0x0769bdaf, 0xfc56fdda, 0x014997bb, 0xffbd8f40, 0x0000ad6e,
-        0x6cea4418, 0x0c0680fe, 0xf4daa718, 0x07530501, 0xfc598f60, 0x014c21db, 0xffbb89a1, 0x000166b6,
-        0x6cce7b97, 0x0b34b7f5, 0xf525a143, 0x073bab28, 0xfc5c8ba5, 0x014e782a, 0xffb996f3, 0x00021ae5,
-        0x6cae7272, 0x0a6519f4, 0xf5710a17, 0x0723b4b4, 0xfc5ff105, 0x01509b14, 0xffb7b728, 0x0002c9fd,
-        0x6c8a2b0f, 0x0997b116, 0xf5bcd7b1, 0x070b2639, 0xfc63bdd3, 0x01528b08, 0xffb5ea31, 0x000373fb,
-        0x6c61a823, 0x08cc873c, 0xf609003f, 0x06f20453, 0xfc67f05a, 0x0154487b, 0xffb42ffc, 0x000418e2,
-        0x6c34ecb5, 0x0803a60a, 0xf6557a00, 0x06d853a2, 0xfc6c86dd, 0x0155d3e8, 0xffb28876, 0x0004b8b3,
-        0x6c03fc1c, 0x073d16e7, 0xf6a23b44, 0x06be18cd, 0xfc717f97, 0x01572dcf, 0xffb0f388, 0x00055371,
-        0x6bced9ff, 0x0678e2fc, 0xf6ef3a6e, 0x06a3587e, 0xfc76d8bc, 0x015856b6, 0xffaf7118, 0x0005e921,
-        0x6b958a54, 0x05b71332, 0xf73c6df4, 0x06881761, 0xfc7c9079, 0x01594f25, 0xffae010b, 0x000679c5,
-        0x6b581163, 0x04f7b037, 0xf789cc61, 0x066c5a27, 0xfc82a4f4, 0x015a17ab, 0xffaca344, 0x00070564,
-        0x6b1673c1, 0x043ac276, 0xf7d74c53, 0x06502583, 0xfc89144d, 0x015ab0db, 0xffab57a1, 0x00078c04,
-        0x6ad0b652, 0x0380521c, 0xf824e480, 0x06337e2a, 0xfc8fdc9f, 0x015b1b4e, 0xffaa1e02, 0x00080dab,
-        0x6a86de48, 0x02c86715, 0xf8728bb3, 0x061668d2, 0xfc96fbfc, 0x015b579e, 0xffa8f641, 0x00088a62,
-        0x6a38f123, 0x0213090c, 0xf8c038d0, 0x05f8ea30, 0xfc9e7074, 0x015b666c, 0xffa7e039, 0x00090230,
-        0x69e6f4b1, 0x01603f6e, 0xf90de2d1, 0x05db06fc, 0xfca63810, 0x015b485b, 0xffa6dbc0, 0x0009751e,
-        0x6990ef0b, 0x00b01162, 0xf95b80cb, 0x05bcc3ed, 0xfcae50d6, 0x015afe14, 0xffa5e8ad, 0x0009e337,
-        0x6936e697, 0x000285d0, 0xf9a909ea, 0x059e25b5, 0xfcb6b8c4, 0x015a8843, 0xffa506d2, 0x000a4c85,
-        0x68d8e206, 0xff57a35e, 0xf9f67577, 0x057f310a, 0xfcbf6dd8, 0x0159e796, 0xffa43603, 0x000ab112,
-        0x6876e855, 0xfeaf706f, 0xfa43bad2, 0x055fea9d, 0xfcc86e09, 0x01591cc0, 0xffa3760e, 0x000b10ec,
-        0x681100c9, 0xfe09f323, 0xfa90d17b, 0x0540571a, 0xfcd1b74c, 0x01582878, 0xffa2c6c2, 0x000b6c1d,
-        0x67a732f4, 0xfd673159, 0xfaddb10c, 0x05207b2f, 0xfcdb4793, 0x01570b77, 0xffa227ec, 0x000bc2b3,
-        0x673986ac, 0xfcc730aa, 0xfb2a513b, 0x05005b82, 0xfce51ccb, 0x0155c678, 0xffa19957, 0x000c14bb,
-        0x66c80413, 0xfc29f670, 0xfb76a9dd, 0x04dffcb6, 0xfcef34e1, 0x01545a3c, 0xffa11acb, 0x000c6244,
-        0x6652b392, 0xfb8f87bd, 0xfbc2b2e4, 0x04bf6369, 0xfcf98dbe, 0x0152c783, 0xffa0ac11, 0x000cab5c,
-        0x65d99dd5, 0xfaf7e963, 0xfc0e6461, 0x049e9433, 0xfd04254a, 0x01510f13, 0xffa04cf0, 0x000cf012,
-        0x655ccbd3, 0xfa631fef, 0xfc59b685, 0x047d93a8, 0xfd0ef969, 0x014f31b2, 0xff9ffd2c, 0x000d3075,
-        0x64dc46c3, 0xf9d12fab, 0xfca4a19f, 0x045c6654, 0xfd1a0801, 0x014d3029, 0xff9fbc89, 0x000d6c97,
-        0x64581823, 0xf9421c9d, 0xfcef1e20, 0x043b10bd, 0xfd254ef4, 0x014b0b45, 0xff9f8ac9, 0x000da486,
-        0x63d049b4, 0xf8b5ea87, 0xfd392498, 0x04199760, 0xfd30cc24, 0x0148c3d2, 0xff9f67ae, 0x000dd854,
-        0x6344e578, 0xf82c9ce7, 0xfd82adba, 0x03f7feb4, 0xfd3c7d73, 0x01465a9f, 0xff9f52f7, 0x000e0812,
-        0x62b5f5b2, 0xf7a636fa, 0xfdcbb25a, 0x03d64b27, 0xfd4860c2, 0x0143d07f, 0xff9f4c65, 0x000e33d3,
-        0x622384e8, 0xf722bbb5, 0xfe142b6e, 0x03b4811d, 0xfd5473f3, 0x01412643, 0xff9f53b4, 0x000e5ba7,
-        0x618d9ddc, 0xf6a22dcf, 0xfe5c120f, 0x0392a4f4, 0xfd60b4e7, 0x013e5cc0, 0xff9f68a1, 0x000e7fa1,
-        0x60f44b91, 0xf6248fb6, 0xfea35f79, 0x0370bafc, 0xfd6d2180, 0x013b74ca, 0xff9f8ae9, 0x000e9fd5,
-        0x60579947, 0xf5a9e398, 0xfeea0d0c, 0x034ec77f, 0xfd79b7a1, 0x01386f3a, 0xff9fba47, 0x000ebc54,
-        0x5fb79278, 0xf5322b61, 0xff30144a, 0x032ccebb, 0xfd86752e, 0x01354ce7, 0xff9ff674, 0x000ed533,
-        0x5f1442dc, 0xf4bd68b6, 0xff756edc, 0x030ad4e1, 0xfd93580d, 0x01320ea9, 0xffa03f2b, 0x000eea84,
-        0x5e6db665, 0xf44b9cfe, 0xffba168d, 0x02e8de19, 0xfda05e23, 0x012eb55a, 0xffa09425, 0x000efc5c,
-        0x5dc3f93c, 0xf3dcc959, 0xfffe054e, 0x02c6ee7f, 0xfdad855b, 0x012b41d3, 0xffa0f519, 0x000f0ace,
-        0x5d1717c4, 0xf370eea9, 0x00413536, 0x02a50a22, 0xfdbacb9e, 0x0127b4f1, 0xffa161bf, 0x000f15ef,
-        0x5c671e96, 0xf3080d8c, 0x0083a081, 0x02833506, 0xfdc82edb, 0x01240f8e, 0xffa1d9cf, 0x000f1dd2,
-        0x5bb41a80, 0xf2a2265e, 0x00c54190, 0x02617321, 0xfdd5ad01, 0x01205285, 0xffa25cfe, 0x000f228d,
-        0x5afe1886, 0xf23f393b, 0x010612eb, 0x023fc85c, 0xfde34403, 0x011c7eb2, 0xffa2eb04, 0x000f2434,
-        0x5a4525df, 0xf1df45fd, 0x01460f41, 0x021e3891, 0xfdf0f1d6, 0x011894f0, 0xffa38395, 0x000f22dc,
-        0x59894ff3, 0xf1824c3e, 0x01853165, 0x01fcc78f, 0xfdfeb475, 0x0114961b, 0xffa42668, 0x000f1e99,
-        0x58caa45b, 0xf1284b58, 0x01c37452, 0x01db7914, 0xfe0c89db, 0x0110830f, 0xffa4d332, 0x000f1781,
-        0x580930e1, 0xf0d14267, 0x0200d32c, 0x01ba50d2, 0xfe1a7009, 0x010c5ca6, 0xffa589a6, 0x000f0da8,
-        0x5745037c, 0xf07d3043, 0x023d493c, 0x0199526b, 0xfe286505, 0x010823ba, 0xffa6497c, 0x000f0125,
-        0x567e2a51, 0xf02c138a, 0x0278d1f2, 0x01788170, 0xfe3666d5, 0x0103d927, 0xffa71266, 0x000ef20b,
-        0x55b4b3af, 0xefddea9a, 0x02b368e6, 0x0157e166, 0xfe447389, 0x00ff7dc4, 0xffa7e41a, 0x000ee070,
-        0x54e8ae13, 0xef92b393, 0x02ed09d7, 0x013775bf, 0xfe528931, 0x00fb126b, 0xffa8be4c, 0x000ecc69,
-        0x541a281e, 0xef4a6c58, 0x0325b0ad, 0x011741df, 0xfe60a5e5, 0x00f697f3, 0xffa9a0b1, 0x000eb60b,
-        0x5349309e, 0xef051290, 0x035d5977, 0x00f7491a, 0xfe6ec7c0, 0x00f20f32, 0xffaa8afe, 0x000e9d6b,
-        0x5275d684, 0xeec2a3a3, 0x0394006a, 0x00d78eb3, 0xfe7cece2, 0x00ed78ff, 0xffab7ce7, 0x000e829e,
-        0x51a028e8, 0xee831cc3, 0x03c9a1e5, 0x00b815da, 0xfe8b1373, 0x00e8d62d, 0xffac7621, 0x000e65ba,
-        0x50c83704, 0xee467ae1, 0x03fe3a6f, 0x0098e1b3, 0xfe99399f, 0x00e4278f, 0xffad7662, 0x000e46d3,
-        0x4fee1037, 0xee0cbab9, 0x0431c6b5, 0x0079f54c, 0xfea75d97, 0x00df6df7, 0xffae7d5f, 0x000e25fd,
-        0x4f11c3fe, 0xedd5d8ca, 0x0464438c, 0x005b53a4, 0xfeb57d92, 0x00daaa34, 0xffaf8acd, 0x000e034f,
-        0x4e3361f7, 0xeda1d15c, 0x0495adf2, 0x003cffa9, 0xfec397cf, 0x00d5dd16, 0xffb09e63, 0x000ddedb,
-        0x4d52f9df, 0xed70a07d, 0x04c6030d, 0x001efc35, 0xfed1aa92, 0x00d10769, 0xffb1b7d8, 0x000db8b7,
-        0x4c709b8e, 0xed424205, 0x04f54029, 0x00014c12, 0xfedfb425, 0x00cc29f7, 0xffb2d6e1, 0x000d90f6,
-        0x4b8c56f8, 0xed16b196, 0x052362ba, 0xffe3f1f7, 0xfeedb2da, 0x00c7458a, 0xffb3fb37, 0x000d67ae,
-        0x4aa63c2c, 0xecedea99, 0x0550685d, 0xffc6f08a, 0xfefba508, 0x00c25ae8, 0xffb52490, 0x000d3cf1,
-        0x49be5b50, 0xecc7e845, 0x057c4ed4, 0xffaa4a5d, 0xff09890f, 0x00bd6ad7, 0xffb652a7, 0x000d10d5,
-        0x48d4c4a2, 0xeca4a59b, 0x05a7140b, 0xff8e01f1, 0xff175d53, 0x00b87619, 0xffb78533, 0x000ce36b,
-        0x47e98874, 0xec841d68, 0x05d0b612, 0xff7219b3, 0xff252042, 0x00b37d70, 0xffb8bbed, 0x000cb4c8,
-        0x46fcb72d, 0xec664a48, 0x05f93324, 0xff5693fe, 0xff32d04f, 0x00ae8198, 0xffb9f691, 0x000c84ff,
-        0x460e6148, 0xec4b26a2, 0x0620899e, 0xff3b731b, 0xff406bf8, 0x00a9834e, 0xffbb34d8, 0x000c5422,
-        0x451e9750, 0xec32acb0, 0x0646b808, 0xff20b93e, 0xff4df1be, 0x00a4834c, 0xffbc767f, 0x000c2245,
-        0x442d69de, 0xec1cd677, 0x066bbd0d, 0xff066889, 0xff5b602c, 0x009f8249, 0xffbdbb42, 0x000bef79,
-        0x433ae99c, 0xec099dcf, 0x068f9781, 0xfeec830d, 0xff68b5d5, 0x009a80f8, 0xffbf02dd, 0x000bbbd2,
-        0x4247273f, 0xebf8fc64, 0x06b2465b, 0xfed30ac5, 0xff75f153, 0x0095800c, 0xffc04d0f, 0x000b8760,
-        0x41523389, 0xebeaebaf, 0x06d3c8bb, 0xfeba0199, 0xff831148, 0x00908034, 0xffc19996, 0x000b5235,
-        0x405c1f43, 0xebdf6500, 0x06f41de3, 0xfea16960, 0xff90145e, 0x008b821b, 0xffc2e832, 0x000b1c64,
-        0x3f64fb40, 0xebd6617b, 0x0713453d, 0xfe8943dc, 0xff9cf947, 0x0086866b, 0xffc438a3, 0x000ae5fc,
-        0x3e6cd85b, 0xebcfda19, 0x07313e56, 0xfe7192bd, 0xffa9bebe, 0x00818dcb, 0xffc58aaa, 0x000aaf0f,
-        0x3d73c772, 0xebcbc7a7, 0x074e08e0, 0xfe5a579d, 0xffb66386, 0x007c98de, 0xffc6de09, 0x000a77ac,
-        0x3c79d968, 0xebca22cc, 0x0769a4b2, 0xfe439407, 0xffc2e669, 0x0077a845, 0xffc83285, 0x000a3fe5,
-        0x3b7f1f23, 0xebcae405, 0x078411c7, 0xfe2d496f, 0xffcf463a, 0x0072bc9d, 0xffc987e0, 0x000a07c9,
-        0x3a83a989, 0xebce03aa, 0x079d503b, 0xfe177937, 0xffdb81d6, 0x006dd680, 0xffcadde1, 0x0009cf67,
-        0x3987897f, 0xebd379eb, 0x07b56051, 0xfe0224b0, 0xffe79820, 0x0068f687, 0xffcc344c, 0x000996ce,
-        0x388acfe9, 0xebdb3ed5, 0x07cc426c, 0xfded4d13, 0xfff38806, 0x00641d44, 0xffcd8aeb, 0x00095e0e,
-        0x378d8da8, 0xebe54a4f, 0x07e1f712, 0xfdd8f38b, 0xffff507b, 0x005f4b4a, 0xffcee183, 0x00092535,
-        0x368fd397, 0xebf1941f, 0x07f67eec, 0xfdc5192d, 0x000af07f, 0x005a8125, 0xffd037e0, 0x0008ec50,
-        0x3591b28b, 0xec0013e8, 0x0809dac3, 0xfdb1befc, 0x00166718, 0x0055bf60, 0xffd18dcc, 0x0008b36e,
-        0x34933b50, 0xec10c12c, 0x081c0b84, 0xfd9ee5e7, 0x0021b355, 0x00510682, 0xffd2e311, 0x00087a9c,
-        0x33947eab, 0xec23934f, 0x082d1239, 0xfd8c8ecc, 0x002cd44d, 0x004c570f, 0xffd4377d, 0x000841e8,
-        0x32958d55, 0xec388194, 0x083cf010, 0xfd7aba74, 0x0037c922, 0x0047b186, 0xffd58ade, 0x0008095d,
-        0x319677fa, 0xec4f8322, 0x084ba654, 0xfd696998, 0x004290fc, 0x00431666, 0xffd6dd02, 0x0007d108,
-        0x30974f3b, 0xec688f02, 0x08593671, 0xfd589cdc, 0x004d2b0e, 0x003e8628, 0xffd82dba, 0x000798f5,
-        0x2f9823a8, 0xec839c22, 0x0865a1f1, 0xfd4854d3, 0x00579691, 0x003a0141, 0xffd97cd6, 0x00076130,
-        0x2e9905c1, 0xeca0a156, 0x0870ea7e, 0xfd3891fd, 0x0061d2ca, 0x00358824, 0xffdaca2a, 0x000729c4,
-        0x2d9a05f4, 0xecbf9558, 0x087b11de, 0xfd2954c8, 0x006bdf05, 0x00311b41, 0xffdc1588, 0x0006f2bb,
-        0x2c9b349e, 0xece06ecb, 0x088419f6, 0xfd1a9d91, 0x0075ba95, 0x002cbb03, 0xffdd5ec6, 0x0006bc21,
-        0x2b9ca203, 0xed032439, 0x088c04c8, 0xfd0c6ca2, 0x007f64da, 0x002867d2, 0xffdea5bb, 0x000685ff,
-        0x2a9e5e57, 0xed27ac16, 0x0892d470, 0xfcfec233, 0x0088dd38, 0x00242213, 0xffdfea3c, 0x0006505f,
-        0x29a079b2, 0xed4dfcc2, 0x08988b2a, 0xfcf19e6b, 0x0092231e, 0x001fea27, 0xffe12c22, 0x00061b4b,
-        0x28a30416, 0xed760c88, 0x089d2b4a, 0xfce50161, 0x009b3605, 0x001bc06b, 0xffe26b48, 0x0005e6cb,
-        0x27a60d6a, 0xed9fd1a2, 0x08a0b740, 0xfcd8eb17, 0x00a4156b, 0x0017a53b, 0xffe3a788, 0x0005b2e8,
-        0x26a9a57b, 0xedcb4237, 0x08a33196, 0xfccd5b82, 0x00acc0da, 0x001398ec, 0xffe4e0bf, 0x00057faa,
-        0x25addbf9, 0xedf8545b, 0x08a49cf0, 0xfcc25285, 0x00b537e1, 0x000f9bd2, 0xffe616c8, 0x00054d1a,
-        0x24b2c075, 0xee26fe17, 0x08a4fc0d, 0xfcb7cff0, 0x00bd7a1c, 0x000bae3c, 0xffe74984, 0x00051b3e,
-        0x23b86263, 0xee573562, 0x08a451c0, 0xfcadd386, 0x00c5872a, 0x0007d075, 0xffe878d3, 0x0004ea1d,
-        0x22bed116, 0xee88f026, 0x08a2a0f8, 0xfca45cf7, 0x00cd5eb7, 0x000402c8, 0xffe9a494, 0x0004b9c0,
-        0x21c61bc0, 0xeebc2444, 0x089fecbb, 0xfc9b6be5, 0x00d50075, 0x00004579, 0xffeaccaa, 0x00048a2b,
-        0x20ce516f, 0xeef0c78d, 0x089c3824, 0xfc92ffe1, 0x00dc6c1e, 0xfffc98c9, 0xffebf0fa, 0x00045b65,
-        0x1fd7810f, 0xef26cfca, 0x08978666, 0xfc8b186d, 0x00e3a175, 0xfff8fcf7, 0xffed1166, 0x00042d74,
-        0x1ee1b965, 0xef5e32bd, 0x0891dac8, 0xfc83b4fc, 0x00eaa045, 0xfff5723d, 0xffee2dd7, 0x0004005e,
-        0x1ded0911, 0xef96e61c, 0x088b38a9, 0xfc7cd4f0, 0x00f16861, 0xfff1f8d2, 0xffef4632, 0x0003d426,
-        0x1cf97e8b, 0xefd0df9a, 0x0883a378, 0xfc76779e, 0x00f7f9a3, 0xffee90eb, 0xfff05a60, 0x0003a8d2,
-        0x1c072823, 0xf00c14e1, 0x087b1ebc, 0xfc709c4d, 0x00fe53ef, 0xffeb3ab8, 0xfff16a4a, 0x00037e65,
-        0x1b1613ff, 0xf0487b98, 0x0871ae0d, 0xfc6b4233, 0x0104772e, 0xffe7f666, 0xfff275db, 0x000354e5,
-        0x1a26501b, 0xf0860962, 0x08675516, 0xfc66687a, 0x010a6353, 0xffe4c41e, 0xfff37d00, 0x00032c54,
-        0x1937ea47, 0xf0c4b3e0, 0x085c1794, 0xfc620e3d, 0x01101858, 0xffe1a408, 0xfff47fa5, 0x000304b7,
-        0x184af025, 0xf10470b0, 0x084ff957, 0xfc5e328c, 0x0115963d, 0xffde9646, 0xfff57db8, 0x0002de0e,
-        0x175f6f2b, 0xf1453571, 0x0842fe3d, 0xfc5ad465, 0x011add0b, 0xffdb9af8, 0xfff67729, 0x0002b85f,
-        0x1675749e, 0xf186f7c0, 0x08352a35, 0xfc57f2be, 0x011fecd3, 0xffd8b23b, 0xfff76be9, 0x000293aa,
-        0x158d0d95, 0xf1c9ad40, 0x0826813e, 0xfc558c7c, 0x0124c5ab, 0xffd5dc28, 0xfff85be8, 0x00026ff2,
-        0x14a646f6, 0xf20d4b92, 0x08170767, 0xfc53a07b, 0x012967b1, 0xffd318d6, 0xfff9471b, 0x00024d39,
-        0x13c12d73, 0xf251c85d, 0x0806c0cb, 0xfc522d88, 0x012dd30a, 0xffd06858, 0xfffa2d74, 0x00022b7f,
-        0x12ddcd8f, 0xf297194d, 0x07f5b193, 0xfc513266, 0x013207e4, 0xffcdcabe, 0xfffb0ee9, 0x00020ac7,
-        0x11fc3395, 0xf2dd3411, 0x07e3ddf7, 0xfc50adcc, 0x01360670, 0xffcb4014, 0xfffbeb70, 0x0001eb10,
-        0x111c6ba0, 0xf3240e61, 0x07d14a38, 0xfc509e64, 0x0139cee9, 0xffc8c866, 0xfffcc300, 0x0001cc5c,
+#include "AudioResamplerSincUp.h"
 };
 
 /*
@@ -197,135 +69,7 @@
  * cmd-line: fir -l 7 -s 48000 -c 17189
  */
 const uint32_t AudioResamplerSinc::mFirCoefsDown[] __attribute__ ((aligned (32))) = {
-        0x5bacb6f4, 0x1ded1a1d, 0xf0398d56, 0x0394f674, 0x0193a5f9, 0xfe66dbeb, 0x00791043, 0xfffe6631,
-        0x5bab6c81, 0x1d3ddccd, 0xf0421d2c, 0x03af9995, 0x01818dc9, 0xfe6bb63e, 0x0079812a, 0xfffdc37d,
-        0x5ba78d37, 0x1c8f2cf9, 0xf04beb1d, 0x03c9a04a, 0x016f8aca, 0xfe70a511, 0x0079e34d, 0xfffd2545,
-        0x5ba1194f, 0x1be11231, 0xf056f2c7, 0x03e309fe, 0x015d9e64, 0xfe75a79f, 0x007a36e2, 0xfffc8b86,
-        0x5b981122, 0x1b3393f8, 0xf0632fb7, 0x03fbd625, 0x014bc9fa, 0xfe7abd23, 0x007a7c20, 0xfffbf639,
-        0x5b8c7530, 0x1a86b9bf, 0xf0709d74, 0x04140449, 0x013a0ee9, 0xfe7fe4db, 0x007ab33d, 0xfffb655b,
-        0x5b7e461a, 0x19da8ae5, 0xf07f3776, 0x042b93fd, 0x01286e86, 0xfe851e05, 0x007adc72, 0xfffad8e4,
-        0x5b6d84a8, 0x192f0eb7, 0xf08ef92d, 0x044284e6, 0x0116ea22, 0xfe8a67dd, 0x007af7f6, 0xfffa50ce,
-        0x5b5a31c6, 0x18844c70, 0xf09fddfe, 0x0458d6b7, 0x01058306, 0xfe8fc1a5, 0x007b0603, 0xfff9cd12,
-        0x5b444e81, 0x17da4b37, 0xf0b1e143, 0x046e8933, 0x00f43a74, 0xfe952a9b, 0x007b06d4, 0xfff94da9,
-        0x5b2bdc0e, 0x17311222, 0xf0c4fe50, 0x04839c29, 0x00e311a9, 0xfe9aa201, 0x007afaa1, 0xfff8d28c,
-        0x5b10dbc2, 0x1688a832, 0xf0d9306d, 0x04980f79, 0x00d209db, 0xfea02719, 0x007ae1a7, 0xfff85bb1,
-        0x5af34f18, 0x15e11453, 0xf0ee72db, 0x04abe310, 0x00c12439, 0xfea5b926, 0x007abc20, 0xfff7e910,
-        0x5ad337af, 0x153a5d5e, 0xf104c0d2, 0x04bf16e9, 0x00b061eb, 0xfeab576d, 0x007a8a49, 0xfff77a9f,
-        0x5ab09748, 0x14948a16, 0xf11c1583, 0x04d1ab0d, 0x009fc413, 0xfeb10134, 0x007a4c5d, 0xfff71057,
-        0x5a8b6fc7, 0x13efa12c, 0xf1346c17, 0x04e39f93, 0x008f4bcb, 0xfeb6b5c0, 0x007a029a, 0xfff6aa2b,
-        0x5a63c336, 0x134ba937, 0xf14dbfb1, 0x04f4f4a2, 0x007efa29, 0xfebc745c, 0x0079ad3d, 0xfff64812,
-        0x5a3993c0, 0x12a8a8bb, 0xf1680b6e, 0x0505aa6a, 0x006ed038, 0xfec23c50, 0x00794c82, 0xfff5ea02,
-        0x5a0ce3b2, 0x1206a625, 0xf1834a63, 0x0515c12d, 0x005ecf01, 0xfec80ce8, 0x0078e0a9, 0xfff58ff0,
-        0x59ddb57f, 0x1165a7cc, 0xf19f77a0, 0x05253938, 0x004ef782, 0xfecde571, 0x007869ee, 0xfff539cf,
-        0x59ac0bba, 0x10c5b3ef, 0xf1bc8e31, 0x053412e4, 0x003f4ab4, 0xfed3c538, 0x0077e891, 0xfff4e794,
-        0x5977e919, 0x1026d0b8, 0xf1da891b, 0x05424e9b, 0x002fc98a, 0xfed9ab8f, 0x00775ccf, 0xfff49934,
-        0x59415075, 0x0f890437, 0xf1f96360, 0x054feccf, 0x002074ed, 0xfedf97c6, 0x0076c6e8, 0xfff44ea3,
-        0x590844c9, 0x0eec5465, 0xf21917ff, 0x055cee03, 0x00114dc3, 0xfee58932, 0x00762719, 0xfff407d2,
-        0x58ccc930, 0x0e50c723, 0xf239a1ef, 0x056952c3, 0x000254e8, 0xfeeb7f27, 0x00757da3, 0xfff3c4b7,
-        0x588ee0ea, 0x0db6623b, 0xf25afc29, 0x05751baa, 0xfff38b32, 0xfef178fc, 0x0074cac4, 0xfff38542,
-        0x584e8f56, 0x0d1d2b5d, 0xf27d219f, 0x0580495c, 0xffe4f171, 0xfef7760c, 0x00740ebb, 0xfff34968,
-        0x580bd7f4, 0x0c85281f, 0xf2a00d43, 0x058adc8d, 0xffd6886d, 0xfefd75af, 0x007349c7, 0xfff3111b,
-        0x57c6be67, 0x0bee5dff, 0xf2c3ba04, 0x0594d5fa, 0xffc850e6, 0xff037744, 0x00727c27, 0xfff2dc4c,
-        0x577f4670, 0x0b58d262, 0xf2e822ce, 0x059e366c, 0xffba4b98, 0xff097a29, 0x0071a61b, 0xfff2aaef,
-        0x573573f2, 0x0ac48a92, 0xf30d428e, 0x05a6feb9, 0xffac7936, 0xff0f7dbf, 0x0070c7e1, 0xfff27cf3,
-        0x56e94af1, 0x0a318bc1, 0xf333142f, 0x05af2fbf, 0xff9eda6d, 0xff15816a, 0x006fe1b8, 0xfff2524c,
-        0x569acf90, 0x099fdb04, 0xf359929a, 0x05b6ca6b, 0xff916fe1, 0xff1b848e, 0x006ef3df, 0xfff22aea,
-        0x564a0610, 0x090f7d57, 0xf380b8ba, 0x05bdcfb2, 0xff843a32, 0xff218692, 0x006dfe94, 0xfff206bf,
-        0x55f6f2d3, 0x0880779d, 0xf3a88179, 0x05c44095, 0xff7739f7, 0xff2786e1, 0x006d0217, 0xfff1e5bb,
-        0x55a19a5c, 0x07f2ce9b, 0xf3d0e7c2, 0x05ca1e1f, 0xff6a6fc1, 0xff2d84e5, 0x006bfea4, 0xfff1c7d0,
-        0x554a0148, 0x076686fc, 0xf3f9e680, 0x05cf6965, 0xff5ddc1a, 0xff33800e, 0x006af47b, 0xfff1acef,
-        0x54f02c56, 0x06dba551, 0xf42378a0, 0x05d42387, 0xff517f86, 0xff3977cb, 0x0069e3d9, 0xfff19508,
-        0x54942061, 0x06522e0f, 0xf44d9912, 0x05d84daf, 0xff455a80, 0xff3f6b8f, 0x0068ccfa, 0xfff1800b,
-        0x5435e263, 0x05ca258f, 0xf47842c5, 0x05dbe90f, 0xff396d7f, 0xff455acf, 0x0067b01e, 0xfff16de9,
-        0x53d57774, 0x0543900d, 0xf4a370ad, 0x05def6e4, 0xff2db8f2, 0xff4b4503, 0x00668d80, 0xfff15e93,
-        0x5372e4c6, 0x04be71ab, 0xf4cf1dbf, 0x05e17873, 0xff223d40, 0xff5129a3, 0x0065655d, 0xfff151f9,
-        0x530e2fac, 0x043ace6e, 0xf4fb44f4, 0x05e36f0d, 0xff16faca, 0xff57082e, 0x006437f1, 0xfff1480b,
-        0x52a75d90, 0x03b8aa40, 0xf527e149, 0x05e4dc08, 0xff0bf1ed, 0xff5ce021, 0x00630577, 0xfff140b9,
-        0x523e73fd, 0x033808eb, 0xf554edbd, 0x05e5c0c6, 0xff0122fc, 0xff62b0fd, 0x0061ce2c, 0xfff13bf3,
-        0x51d37897, 0x02b8ee22, 0xf5826555, 0x05e61eae, 0xfef68e45, 0xff687a47, 0x00609249, 0xfff139aa,
-        0x5166711c, 0x023b5d76, 0xf5b0431a, 0x05e5f733, 0xfeec340f, 0xff6e3b84, 0x005f520a, 0xfff139cd,
-        0x50f76368, 0x01bf5a5e, 0xf5de8218, 0x05e54bcd, 0xfee2149b, 0xff73f43d, 0x005e0da8, 0xfff13c4c,
-        0x5086556f, 0x0144e834, 0xf60d1d63, 0x05e41dfe, 0xfed83023, 0xff79a3fe, 0x005cc55c, 0xfff14119,
-        0x50134d3e, 0x00cc0a36, 0xf63c1012, 0x05e26f4e, 0xfece86db, 0xff7f4a54, 0x005b7961, 0xfff14821,
-        0x4f9e50ff, 0x0054c382, 0xf66b5544, 0x05e0414d, 0xfec518f1, 0xff84e6d0, 0x005a29ed, 0xfff15156,
-        0x4f2766f2, 0xffdf171b, 0xf69ae81d, 0x05dd9593, 0xfebbe68c, 0xff8a7905, 0x0058d738, 0xfff15ca8,
-        0x4eae9571, 0xff6b07e7, 0xf6cac3c7, 0x05da6dbe, 0xfeb2efcd, 0xff900089, 0x0057817b, 0xfff16a07,
-        0x4e33e2ee, 0xfef898ae, 0xf6fae373, 0x05d6cb72, 0xfeaa34d0, 0xff957cf4, 0x005628ec, 0xfff17962,
-        0x4db755f3, 0xfe87cc1b, 0xf72b425b, 0x05d2b05c, 0xfea1b5a9, 0xff9aede0, 0x0054cdc0, 0xfff18aab,
-        0x4d38f520, 0xfe18a4bc, 0xf75bdbbd, 0x05ce1e2d, 0xfe997268, 0xffa052ec, 0x0053702d, 0xfff19dd1,
-        0x4cb8c72e, 0xfdab2501, 0xf78caae0, 0x05c9169d, 0xfe916b15, 0xffa5abb8, 0x00521068, 0xfff1b2c5,
-        0x4c36d2eb, 0xfd3f4f3d, 0xf7bdab16, 0x05c39b6a, 0xfe899fb2, 0xffaaf7e6, 0x0050aea5, 0xfff1c976,
-        0x4bb31f3c, 0xfcd525a5, 0xf7eed7b4, 0x05bdae57, 0xfe82103f, 0xffb0371c, 0x004f4b17, 0xfff1e1d6,
-        0x4b2db31a, 0xfc6caa53, 0xf8202c1c, 0x05b7512e, 0xfe7abcb1, 0xffb56902, 0x004de5f1, 0xfff1fbd5,
-        0x4aa69594, 0xfc05df40, 0xf851a3b6, 0x05b085bc, 0xfe73a4fb, 0xffba8d44, 0x004c7f66, 0xfff21764,
-        0x4a1dcdce, 0xfba0c64b, 0xf88339f5, 0x05a94dd5, 0xfe6cc909, 0xffbfa38d, 0x004b17a6, 0xfff23473,
-        0x499362ff, 0xfb3d6133, 0xf8b4ea55, 0x05a1ab52, 0xfe6628c1, 0xffc4ab8f, 0x0049aee3, 0xfff252f3,
-        0x49075c72, 0xfadbb19a, 0xf8e6b059, 0x0599a00e, 0xfe5fc405, 0xffc9a4fc, 0x0048454b, 0xfff272d6,
-        0x4879c185, 0xfa7bb908, 0xf9188793, 0x05912dea, 0xfe599aaf, 0xffce8f8a, 0x0046db0f, 0xfff2940b,
-        0x47ea99a9, 0xfa1d78e3, 0xf94a6b9b, 0x058856cd, 0xfe53ac97, 0xffd36af1, 0x0045705c, 0xfff2b686,
-        0x4759ec60, 0xf9c0f276, 0xf97c5815, 0x057f1c9e, 0xfe4df98e, 0xffd836eb, 0x00440561, 0xfff2da36,
-        0x46c7c140, 0xf96626f0, 0xf9ae48af, 0x0575814c, 0xfe48815e, 0xffdcf336, 0x00429a4a, 0xfff2ff0d,
-        0x46341fed, 0xf90d1761, 0xf9e03924, 0x056b86c6, 0xfe4343d0, 0xffe19f91, 0x00412f43, 0xfff324fd,
-        0x459f101d, 0xf8b5c4be, 0xfa122537, 0x05612f00, 0xfe3e40a6, 0xffe63bc0, 0x003fc478, 0xfff34bf9,
-        0x45089996, 0xf8602fdc, 0xfa4408ba, 0x05567bf1, 0xfe39779a, 0xffeac787, 0x003e5a12, 0xfff373f0,
-        0x4470c42d, 0xf80c5977, 0xfa75df87, 0x054b6f92, 0xfe34e867, 0xffef42af, 0x003cf03d, 0xfff39cd7,
-        0x43d797c7, 0xf7ba422b, 0xfaa7a586, 0x05400be1, 0xfe3092bf, 0xfff3ad01, 0x003b871f, 0xfff3c69f,
-        0x433d1c56, 0xf769ea78, 0xfad956ab, 0x053452dc, 0xfe2c7650, 0xfff8064b, 0x003a1ee3, 0xfff3f13a,
-        0x42a159dc, 0xf71b52c4, 0xfb0aeef6, 0x05284685, 0xfe2892c5, 0xfffc4e5c, 0x0038b7ae, 0xfff41c9c,
-        0x42045865, 0xf6ce7b57, 0xfb3c6a73, 0x051be8dd, 0xfe24e7c3, 0x00008507, 0x003751a7, 0xfff448b7,
-        0x4166200e, 0xf683645a, 0xfb6dc53c, 0x050f3bec, 0xfe2174ec, 0x0004aa1f, 0x0035ecf4, 0xfff4757e,
-        0x40c6b8fd, 0xf63a0ddf, 0xfb9efb77, 0x050241b6, 0xfe1e39da, 0x0008bd7c, 0x003489b9, 0xfff4a2e5,
-        0x40262b65, 0xf5f277d9, 0xfbd00956, 0x04f4fc46, 0xfe1b3628, 0x000cbef7, 0x0033281a, 0xfff4d0de,
-        0x3f847f83, 0xf5aca21f, 0xfc00eb1b, 0x04e76da3, 0xfe18696a, 0x0010ae6e, 0x0031c83a, 0xfff4ff5d,
-        0x3ee1bda2, 0xf5688c6d, 0xfc319d13, 0x04d997d8, 0xfe15d32f, 0x00148bbd, 0x00306a3b, 0xfff52e57,
-        0x3e3dee13, 0xf5263665, 0xfc621b9a, 0x04cb7cf2, 0xfe137304, 0x001856c7, 0x002f0e3f, 0xfff55dbf,
-        0x3d991932, 0xf4e59f8a, 0xfc926319, 0x04bd1efb, 0xfe114872, 0x001c0f6e, 0x002db466, 0xfff58d89,
-        0x3cf34766, 0xf4a6c748, 0xfcc27008, 0x04ae8000, 0xfe0f52fc, 0x001fb599, 0x002c5cd0, 0xfff5bdaa,
-        0x3c4c811c, 0xf469aced, 0xfcf23eec, 0x049fa20f, 0xfe0d9224, 0x0023492f, 0x002b079a, 0xfff5ee17,
-        0x3ba4cec9, 0xf42e4faf, 0xfd21cc59, 0x04908733, 0xfe0c0567, 0x0026ca1c, 0x0029b4e4, 0xfff61ec5,
-        0x3afc38eb, 0xf3f4aea6, 0xfd5114f0, 0x0481317a, 0xfe0aac3f, 0x002a384c, 0x002864c9, 0xfff64fa8,
-        0x3a52c805, 0xf3bcc8d3, 0xfd801564, 0x0471a2ef, 0xfe098622, 0x002d93ae, 0x00271766, 0xfff680b5,
-        0x39a884a1, 0xf3869d1a, 0xfdaeca73, 0x0461dda0, 0xfe089283, 0x0030dc34, 0x0025ccd7, 0xfff6b1e4,
-        0x38fd774e, 0xf3522a49, 0xfddd30eb, 0x0451e396, 0xfe07d0d3, 0x003411d2, 0x00248535, 0xfff6e329,
-        0x3851a8a2, 0xf31f6f0f, 0xfe0b45aa, 0x0441b6dd, 0xfe07407d, 0x0037347d, 0x0023409a, 0xfff7147a,
-        0x37a52135, 0xf2ee6a07, 0xfe39059b, 0x0431597d, 0xfe06e0eb, 0x003a442e, 0x0021ff1f, 0xfff745cd,
-        0x36f7e9a4, 0xf2bf19ae, 0xfe666dbc, 0x0420cd80, 0xfe06b184, 0x003d40e0, 0x0020c0dc, 0xfff7771a,
-        0x364a0a90, 0xf2917c6d, 0xfe937b15, 0x041014eb, 0xfe06b1ac, 0x00402a8e, 0x001f85e6, 0xfff7a857,
-        0x359b8c9d, 0xf265908f, 0xfec02ac2, 0x03ff31c3, 0xfe06e0c4, 0x00430137, 0x001e4e56, 0xfff7d97a,
-        0x34ec786f, 0xf23b544b, 0xfeec79ec, 0x03ee260d, 0xfe073e2a, 0x0045c4dd, 0x001d1a3f, 0xfff80a7c,
-        0x343cd6af, 0xf212c5be, 0xff1865cd, 0x03dcf3ca, 0xfe07c93a, 0x00487582, 0x001be9b7, 0xfff83b52,
-        0x338cb004, 0xf1ebe2ec, 0xff43ebac, 0x03cb9cf9, 0xfe08814e, 0x004b132b, 0x001abcd0, 0xfff86bf6,
-        0x32dc0d17, 0xf1c6a9c3, 0xff6f08e4, 0x03ba2398, 0xfe0965bc, 0x004d9dde, 0x0019939d, 0xfff89c60,
-        0x322af693, 0xf1a3181a, 0xff99badb, 0x03a889a1, 0xfe0a75da, 0x005015a5, 0x00186e31, 0xfff8cc86,
-        0x3179751f, 0xf1812bb0, 0xffc3ff0c, 0x0396d10c, 0xfe0bb0f9, 0x00527a8a, 0x00174c9c, 0xfff8fc62,
-        0x30c79163, 0xf160e22d, 0xffedd2fd, 0x0384fbd1, 0xfe0d166b, 0x0054cc9a, 0x00162eef, 0xfff92bec,
-        0x30155404, 0xf1423924, 0x00173447, 0x03730be0, 0xfe0ea57e, 0x00570be4, 0x00151538, 0xfff95b1e,
-        0x2f62c5a7, 0xf1252e0f, 0x00402092, 0x0361032a, 0xfe105d7e, 0x00593877, 0x0013ff88, 0xfff989ef,
-        0x2eafeeed, 0xf109be56, 0x00689598, 0x034ee39b, 0xfe123db6, 0x005b5267, 0x0012edea, 0xfff9b85b,
-        0x2dfcd873, 0xf0efe748, 0x0090911f, 0x033caf1d, 0xfe144570, 0x005d59c6, 0x0011e06d, 0xfff9e65a,
-        0x2d498ad3, 0xf0d7a622, 0x00b81102, 0x032a6796, 0xfe1673f2, 0x005f4eac, 0x0010d71d, 0xfffa13e5,
-        0x2c960ea3, 0xf0c0f808, 0x00df1328, 0x03180ee7, 0xfe18c884, 0x0061312e, 0x000fd205, 0xfffa40f8,
-        0x2be26c73, 0xf0abda0e, 0x0105958c, 0x0305a6f0, 0xfe1b4268, 0x00630167, 0x000ed130, 0xfffa6d8d,
-        0x2b2eaccf, 0xf0984931, 0x012b9635, 0x02f3318a, 0xfe1de0e2, 0x0064bf71, 0x000dd4a7, 0xfffa999d,
-        0x2a7ad83c, 0xf086425a, 0x0151133e, 0x02e0b08d, 0xfe20a335, 0x00666b68, 0x000cdc74, 0xfffac525,
-        0x29c6f738, 0xf075c260, 0x01760ad1, 0x02ce25ca, 0xfe2388a1, 0x0068056b, 0x000be89f, 0xfffaf01e,
-        0x2913123c, 0xf066c606, 0x019a7b27, 0x02bb9310, 0xfe269065, 0x00698d98, 0x000af931, 0xfffb1a84,
-        0x285f31b7, 0xf05949fb, 0x01be628c, 0x02a8fa2a, 0xfe29b9c1, 0x006b0411, 0x000a0e2f, 0xfffb4453,
-        0x27ab5e12, 0xf04d4ade, 0x01e1bf58, 0x02965cdb, 0xfe2d03f2, 0x006c68f8, 0x000927a0, 0xfffb6d86,
-        0x26f79fab, 0xf042c539, 0x02048ff8, 0x0283bce6, 0xfe306e35, 0x006dbc71, 0x00084589, 0xfffb961a,
-        0x2643feda, 0xf039b587, 0x0226d2e6, 0x02711c05, 0xfe33f7c7, 0x006efea0, 0x000767f0, 0xfffbbe09,
-        0x259083eb, 0xf032182f, 0x024886ad, 0x025e7bf0, 0xfe379fe3, 0x00702fae, 0x00068ed8, 0xfffbe552,
-        0x24dd3721, 0xf02be98a, 0x0269a9e9, 0x024bde5a, 0xfe3b65c4, 0x00714fc0, 0x0005ba46, 0xfffc0bef,
-        0x242a20b3, 0xf02725dc, 0x028a3b44, 0x023944ee, 0xfe3f48a5, 0x00725f02, 0x0004ea3a, 0xfffc31df,
-        0x237748cf, 0xf023c95d, 0x02aa397b, 0x0226b156, 0xfe4347c0, 0x00735d9c, 0x00041eb9, 0xfffc571e,
-        0x22c4b795, 0xf021d031, 0x02c9a359, 0x02142533, 0xfe476250, 0x00744bba, 0x000357c2, 0xfffc7ba9,
-        0x2212751a, 0xf0213671, 0x02e877b9, 0x0201a223, 0xfe4b978e, 0x0075298a, 0x00029558, 0xfffc9f7e,
-        0x21608968, 0xf021f823, 0x0306b586, 0x01ef29be, 0xfe4fe6b3, 0x0075f739, 0x0001d779, 0xfffcc29a,
-        0x20aefc79, 0xf0241140, 0x03245bbc, 0x01dcbd96, 0xfe544efb, 0x0076b4f5, 0x00011e26, 0xfffce4fc,
-        0x1ffdd63b, 0xf0277db1, 0x03416966, 0x01ca5f37, 0xfe58cf9d, 0x007762f0, 0x0000695e, 0xfffd06a1,
-        0x1f4d1e8e, 0xf02c3953, 0x035ddd9e, 0x01b81028, 0xfe5d67d4, 0x0078015a, 0xffffb91f, 0xfffd2787,
-        0x1e9cdd43, 0xf0323ff5, 0x0379b790, 0x01a5d1ea, 0xfe6216db, 0x00789065, 0xffff0d66, 0xfffd47ae,
-        0x1ded1a1d, 0xf0398d56, 0x0394f674, 0x0193a5f9, 0xfe66dbeb, 0x00791043, 0xfffe6631, 0xfffd6713,
+#include "AudioResamplerSincDown.h"
 };
 
 // we use 15 bits to interpolate between these samples
@@ -521,7 +265,8 @@
     if (mConstants == &veryHighQualityConstants && readResampleCoefficients) {
         mFirCoefs = readResampleCoefficients( mInSampleRate <= mSampleRate );
     } else {
-        mFirCoefs = (const int32_t *) ((mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown);
+        mFirCoefs = (const int32_t *)
+                ((mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown);
     }
 
     // select the appropriate resampler
@@ -856,4 +601,4 @@
     }
 }
 // ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/services/audioflinger/AudioResamplerSinc.h b/services/audioflinger/AudioResamplerSinc.h
index 4691d0a..6d8e85d 100644
--- a/services/audioflinger/AudioResamplerSinc.h
+++ b/services/audioflinger/AudioResamplerSinc.h
@@ -95,6 +95,6 @@
 };
 
 // ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
 
 #endif /*ANDROID_AUDIO_RESAMPLER_SINC_H*/
diff --git a/services/audioflinger/AudioResamplerSincDown.h b/services/audioflinger/AudioResamplerSincDown.h
new file mode 100644
index 0000000..2d0fb86
--- /dev/null
+++ b/services/audioflinger/AudioResamplerSincDown.h
@@ -0,0 +1,131 @@
+// cmd-line: fir -l 7 -s48000 -c 17189
+
+    0x5bacb6f4, 0x1ded1a1d, 0xf0398d56, 0x0394f674, 0x0193a5f9, 0xfe66dbeb, 0x00791043, 0xfffe6631,
+    0x5bab6c81, 0x1d3ddccd, 0xf0421d2c, 0x03af9995, 0x01818dc9, 0xfe6bb63e, 0x0079812a, 0xfffdc37d,
+    0x5ba78d37, 0x1c8f2cf9, 0xf04beb1d, 0x03c9a04a, 0x016f8aca, 0xfe70a511, 0x0079e34d, 0xfffd2545,
+    0x5ba1194f, 0x1be11231, 0xf056f2c7, 0x03e309fe, 0x015d9e64, 0xfe75a79f, 0x007a36e2, 0xfffc8b86,
+    0x5b981122, 0x1b3393f8, 0xf0632fb7, 0x03fbd625, 0x014bc9fa, 0xfe7abd23, 0x007a7c20, 0xfffbf639,
+    0x5b8c7530, 0x1a86b9bf, 0xf0709d74, 0x04140449, 0x013a0ee9, 0xfe7fe4db, 0x007ab33d, 0xfffb655b,
+    0x5b7e461a, 0x19da8ae5, 0xf07f3776, 0x042b93fd, 0x01286e86, 0xfe851e05, 0x007adc72, 0xfffad8e4,
+    0x5b6d84a8, 0x192f0eb7, 0xf08ef92d, 0x044284e6, 0x0116ea22, 0xfe8a67dd, 0x007af7f6, 0xfffa50ce,
+    0x5b5a31c6, 0x18844c70, 0xf09fddfe, 0x0458d6b7, 0x01058306, 0xfe8fc1a5, 0x007b0603, 0xfff9cd12,
+    0x5b444e81, 0x17da4b37, 0xf0b1e143, 0x046e8933, 0x00f43a74, 0xfe952a9b, 0x007b06d4, 0xfff94da9,
+    0x5b2bdc0e, 0x17311222, 0xf0c4fe50, 0x04839c29, 0x00e311a9, 0xfe9aa201, 0x007afaa1, 0xfff8d28c,
+    0x5b10dbc2, 0x1688a832, 0xf0d9306d, 0x04980f79, 0x00d209db, 0xfea02719, 0x007ae1a7, 0xfff85bb1,
+    0x5af34f18, 0x15e11453, 0xf0ee72db, 0x04abe310, 0x00c12439, 0xfea5b926, 0x007abc20, 0xfff7e910,
+    0x5ad337af, 0x153a5d5e, 0xf104c0d2, 0x04bf16e9, 0x00b061eb, 0xfeab576d, 0x007a8a49, 0xfff77a9f,
+    0x5ab09748, 0x14948a16, 0xf11c1583, 0x04d1ab0d, 0x009fc413, 0xfeb10134, 0x007a4c5d, 0xfff71057,
+    0x5a8b6fc7, 0x13efa12c, 0xf1346c17, 0x04e39f93, 0x008f4bcb, 0xfeb6b5c0, 0x007a029a, 0xfff6aa2b,
+    0x5a63c336, 0x134ba937, 0xf14dbfb1, 0x04f4f4a2, 0x007efa29, 0xfebc745c, 0x0079ad3d, 0xfff64812,
+    0x5a3993c0, 0x12a8a8bb, 0xf1680b6e, 0x0505aa6a, 0x006ed038, 0xfec23c50, 0x00794c82, 0xfff5ea02,
+    0x5a0ce3b2, 0x1206a625, 0xf1834a63, 0x0515c12d, 0x005ecf01, 0xfec80ce8, 0x0078e0a9, 0xfff58ff0,
+    0x59ddb57f, 0x1165a7cc, 0xf19f77a0, 0x05253938, 0x004ef782, 0xfecde571, 0x007869ee, 0xfff539cf,
+    0x59ac0bba, 0x10c5b3ef, 0xf1bc8e31, 0x053412e4, 0x003f4ab4, 0xfed3c538, 0x0077e891, 0xfff4e794,
+    0x5977e919, 0x1026d0b8, 0xf1da891b, 0x05424e9b, 0x002fc98a, 0xfed9ab8f, 0x00775ccf, 0xfff49934,
+    0x59415075, 0x0f890437, 0xf1f96360, 0x054feccf, 0x002074ed, 0xfedf97c6, 0x0076c6e8, 0xfff44ea3,
+    0x590844c9, 0x0eec5465, 0xf21917ff, 0x055cee03, 0x00114dc3, 0xfee58932, 0x00762719, 0xfff407d2,
+    0x58ccc930, 0x0e50c723, 0xf239a1ef, 0x056952c3, 0x000254e8, 0xfeeb7f27, 0x00757da3, 0xfff3c4b7,
+    0x588ee0ea, 0x0db6623b, 0xf25afc29, 0x05751baa, 0xfff38b32, 0xfef178fc, 0x0074cac4, 0xfff38542,
+    0x584e8f56, 0x0d1d2b5d, 0xf27d219f, 0x0580495c, 0xffe4f171, 0xfef7760c, 0x00740ebb, 0xfff34968,
+    0x580bd7f4, 0x0c85281f, 0xf2a00d43, 0x058adc8d, 0xffd6886d, 0xfefd75af, 0x007349c7, 0xfff3111b,
+    0x57c6be67, 0x0bee5dff, 0xf2c3ba04, 0x0594d5fa, 0xffc850e6, 0xff037744, 0x00727c27, 0xfff2dc4c,
+    0x577f4670, 0x0b58d262, 0xf2e822ce, 0x059e366c, 0xffba4b98, 0xff097a29, 0x0071a61b, 0xfff2aaef,
+    0x573573f2, 0x0ac48a92, 0xf30d428e, 0x05a6feb9, 0xffac7936, 0xff0f7dbf, 0x0070c7e1, 0xfff27cf3,
+    0x56e94af1, 0x0a318bc1, 0xf333142f, 0x05af2fbf, 0xff9eda6d, 0xff15816a, 0x006fe1b8, 0xfff2524c,
+    0x569acf90, 0x099fdb04, 0xf359929a, 0x05b6ca6b, 0xff916fe1, 0xff1b848e, 0x006ef3df, 0xfff22aea,
+    0x564a0610, 0x090f7d57, 0xf380b8ba, 0x05bdcfb2, 0xff843a32, 0xff218692, 0x006dfe94, 0xfff206bf,
+    0x55f6f2d3, 0x0880779d, 0xf3a88179, 0x05c44095, 0xff7739f7, 0xff2786e1, 0x006d0217, 0xfff1e5bb,
+    0x55a19a5c, 0x07f2ce9b, 0xf3d0e7c2, 0x05ca1e1f, 0xff6a6fc1, 0xff2d84e5, 0x006bfea4, 0xfff1c7d0,
+    0x554a0148, 0x076686fc, 0xf3f9e680, 0x05cf6965, 0xff5ddc1a, 0xff33800e, 0x006af47b, 0xfff1acef,
+    0x54f02c56, 0x06dba551, 0xf42378a0, 0x05d42387, 0xff517f86, 0xff3977cb, 0x0069e3d9, 0xfff19508,
+    0x54942061, 0x06522e0f, 0xf44d9912, 0x05d84daf, 0xff455a80, 0xff3f6b8f, 0x0068ccfa, 0xfff1800b,
+    0x5435e263, 0x05ca258f, 0xf47842c5, 0x05dbe90f, 0xff396d7f, 0xff455acf, 0x0067b01e, 0xfff16de9,
+    0x53d57774, 0x0543900d, 0xf4a370ad, 0x05def6e4, 0xff2db8f2, 0xff4b4503, 0x00668d80, 0xfff15e93,
+    0x5372e4c6, 0x04be71ab, 0xf4cf1dbf, 0x05e17873, 0xff223d40, 0xff5129a3, 0x0065655d, 0xfff151f9,
+    0x530e2fac, 0x043ace6e, 0xf4fb44f4, 0x05e36f0d, 0xff16faca, 0xff57082e, 0x006437f1, 0xfff1480b,
+    0x52a75d90, 0x03b8aa40, 0xf527e149, 0x05e4dc08, 0xff0bf1ed, 0xff5ce021, 0x00630577, 0xfff140b9,
+    0x523e73fd, 0x033808eb, 0xf554edbd, 0x05e5c0c6, 0xff0122fc, 0xff62b0fd, 0x0061ce2c, 0xfff13bf3,
+    0x51d37897, 0x02b8ee22, 0xf5826555, 0x05e61eae, 0xfef68e45, 0xff687a47, 0x00609249, 0xfff139aa,
+    0x5166711c, 0x023b5d76, 0xf5b0431a, 0x05e5f733, 0xfeec340f, 0xff6e3b84, 0x005f520a, 0xfff139cd,
+    0x50f76368, 0x01bf5a5e, 0xf5de8218, 0x05e54bcd, 0xfee2149b, 0xff73f43d, 0x005e0da8, 0xfff13c4c,
+    0x5086556f, 0x0144e834, 0xf60d1d63, 0x05e41dfe, 0xfed83023, 0xff79a3fe, 0x005cc55c, 0xfff14119,
+    0x50134d3e, 0x00cc0a36, 0xf63c1012, 0x05e26f4e, 0xfece86db, 0xff7f4a54, 0x005b7961, 0xfff14821,
+    0x4f9e50ff, 0x0054c382, 0xf66b5544, 0x05e0414d, 0xfec518f1, 0xff84e6d0, 0x005a29ed, 0xfff15156,
+    0x4f2766f2, 0xffdf171b, 0xf69ae81d, 0x05dd9593, 0xfebbe68c, 0xff8a7905, 0x0058d738, 0xfff15ca8,
+    0x4eae9571, 0xff6b07e7, 0xf6cac3c7, 0x05da6dbe, 0xfeb2efcd, 0xff900089, 0x0057817b, 0xfff16a07,
+    0x4e33e2ee, 0xfef898ae, 0xf6fae373, 0x05d6cb72, 0xfeaa34d0, 0xff957cf4, 0x005628ec, 0xfff17962,
+    0x4db755f3, 0xfe87cc1b, 0xf72b425b, 0x05d2b05c, 0xfea1b5a9, 0xff9aede0, 0x0054cdc0, 0xfff18aab,
+    0x4d38f520, 0xfe18a4bc, 0xf75bdbbd, 0x05ce1e2d, 0xfe997268, 0xffa052ec, 0x0053702d, 0xfff19dd1,
+    0x4cb8c72e, 0xfdab2501, 0xf78caae0, 0x05c9169d, 0xfe916b15, 0xffa5abb8, 0x00521068, 0xfff1b2c5,
+    0x4c36d2eb, 0xfd3f4f3d, 0xf7bdab16, 0x05c39b6a, 0xfe899fb2, 0xffaaf7e6, 0x0050aea5, 0xfff1c976,
+    0x4bb31f3c, 0xfcd525a5, 0xf7eed7b4, 0x05bdae57, 0xfe82103f, 0xffb0371c, 0x004f4b17, 0xfff1e1d6,
+    0x4b2db31a, 0xfc6caa53, 0xf8202c1c, 0x05b7512e, 0xfe7abcb1, 0xffb56902, 0x004de5f1, 0xfff1fbd5,
+    0x4aa69594, 0xfc05df40, 0xf851a3b6, 0x05b085bc, 0xfe73a4fb, 0xffba8d44, 0x004c7f66, 0xfff21764,
+    0x4a1dcdce, 0xfba0c64b, 0xf88339f5, 0x05a94dd5, 0xfe6cc909, 0xffbfa38d, 0x004b17a6, 0xfff23473,
+    0x499362ff, 0xfb3d6133, 0xf8b4ea55, 0x05a1ab52, 0xfe6628c1, 0xffc4ab8f, 0x0049aee3, 0xfff252f3,
+    0x49075c72, 0xfadbb19a, 0xf8e6b059, 0x0599a00e, 0xfe5fc405, 0xffc9a4fc, 0x0048454b, 0xfff272d6,
+    0x4879c185, 0xfa7bb908, 0xf9188793, 0x05912dea, 0xfe599aaf, 0xffce8f8a, 0x0046db0f, 0xfff2940b,
+    0x47ea99a9, 0xfa1d78e3, 0xf94a6b9b, 0x058856cd, 0xfe53ac97, 0xffd36af1, 0x0045705c, 0xfff2b686,
+    0x4759ec60, 0xf9c0f276, 0xf97c5815, 0x057f1c9e, 0xfe4df98e, 0xffd836eb, 0x00440561, 0xfff2da36,
+    0x46c7c140, 0xf96626f0, 0xf9ae48af, 0x0575814c, 0xfe48815e, 0xffdcf336, 0x00429a4a, 0xfff2ff0d,
+    0x46341fed, 0xf90d1761, 0xf9e03924, 0x056b86c6, 0xfe4343d0, 0xffe19f91, 0x00412f43, 0xfff324fd,
+    0x459f101d, 0xf8b5c4be, 0xfa122537, 0x05612f00, 0xfe3e40a6, 0xffe63bc0, 0x003fc478, 0xfff34bf9,
+    0x45089996, 0xf8602fdc, 0xfa4408ba, 0x05567bf1, 0xfe39779a, 0xffeac787, 0x003e5a12, 0xfff373f0,
+    0x4470c42d, 0xf80c5977, 0xfa75df87, 0x054b6f92, 0xfe34e867, 0xffef42af, 0x003cf03d, 0xfff39cd7,
+    0x43d797c7, 0xf7ba422b, 0xfaa7a586, 0x05400be1, 0xfe3092bf, 0xfff3ad01, 0x003b871f, 0xfff3c69f,
+    0x433d1c56, 0xf769ea78, 0xfad956ab, 0x053452dc, 0xfe2c7650, 0xfff8064b, 0x003a1ee3, 0xfff3f13a,
+    0x42a159dc, 0xf71b52c4, 0xfb0aeef6, 0x05284685, 0xfe2892c5, 0xfffc4e5c, 0x0038b7ae, 0xfff41c9c,
+    0x42045865, 0xf6ce7b57, 0xfb3c6a73, 0x051be8dd, 0xfe24e7c3, 0x00008507, 0x003751a7, 0xfff448b7,
+    0x4166200e, 0xf683645a, 0xfb6dc53c, 0x050f3bec, 0xfe2174ec, 0x0004aa1f, 0x0035ecf4, 0xfff4757e,
+    0x40c6b8fd, 0xf63a0ddf, 0xfb9efb77, 0x050241b6, 0xfe1e39da, 0x0008bd7c, 0x003489b9, 0xfff4a2e5,
+    0x40262b65, 0xf5f277d9, 0xfbd00956, 0x04f4fc46, 0xfe1b3628, 0x000cbef7, 0x0033281a, 0xfff4d0de,
+    0x3f847f83, 0xf5aca21f, 0xfc00eb1b, 0x04e76da3, 0xfe18696a, 0x0010ae6e, 0x0031c83a, 0xfff4ff5d,
+    0x3ee1bda2, 0xf5688c6d, 0xfc319d13, 0x04d997d8, 0xfe15d32f, 0x00148bbd, 0x00306a3b, 0xfff52e57,
+    0x3e3dee13, 0xf5263665, 0xfc621b9a, 0x04cb7cf2, 0xfe137304, 0x001856c7, 0x002f0e3f, 0xfff55dbf,
+    0x3d991932, 0xf4e59f8a, 0xfc926319, 0x04bd1efb, 0xfe114872, 0x001c0f6e, 0x002db466, 0xfff58d89,
+    0x3cf34766, 0xf4a6c748, 0xfcc27008, 0x04ae8000, 0xfe0f52fc, 0x001fb599, 0x002c5cd0, 0xfff5bdaa,
+    0x3c4c811c, 0xf469aced, 0xfcf23eec, 0x049fa20f, 0xfe0d9224, 0x0023492f, 0x002b079a, 0xfff5ee17,
+    0x3ba4cec9, 0xf42e4faf, 0xfd21cc59, 0x04908733, 0xfe0c0567, 0x0026ca1c, 0x0029b4e4, 0xfff61ec5,
+    0x3afc38eb, 0xf3f4aea6, 0xfd5114f0, 0x0481317a, 0xfe0aac3f, 0x002a384c, 0x002864c9, 0xfff64fa8,
+    0x3a52c805, 0xf3bcc8d3, 0xfd801564, 0x0471a2ef, 0xfe098622, 0x002d93ae, 0x00271766, 0xfff680b5,
+    0x39a884a1, 0xf3869d1a, 0xfdaeca73, 0x0461dda0, 0xfe089283, 0x0030dc34, 0x0025ccd7, 0xfff6b1e4,
+    0x38fd774e, 0xf3522a49, 0xfddd30eb, 0x0451e396, 0xfe07d0d3, 0x003411d2, 0x00248535, 0xfff6e329,
+    0x3851a8a2, 0xf31f6f0f, 0xfe0b45aa, 0x0441b6dd, 0xfe07407d, 0x0037347d, 0x0023409a, 0xfff7147a,
+    0x37a52135, 0xf2ee6a07, 0xfe39059b, 0x0431597d, 0xfe06e0eb, 0x003a442e, 0x0021ff1f, 0xfff745cd,
+    0x36f7e9a4, 0xf2bf19ae, 0xfe666dbc, 0x0420cd80, 0xfe06b184, 0x003d40e0, 0x0020c0dc, 0xfff7771a,
+    0x364a0a90, 0xf2917c6d, 0xfe937b15, 0x041014eb, 0xfe06b1ac, 0x00402a8e, 0x001f85e6, 0xfff7a857,
+    0x359b8c9d, 0xf265908f, 0xfec02ac2, 0x03ff31c3, 0xfe06e0c4, 0x00430137, 0x001e4e56, 0xfff7d97a,
+    0x34ec786f, 0xf23b544b, 0xfeec79ec, 0x03ee260d, 0xfe073e2a, 0x0045c4dd, 0x001d1a3f, 0xfff80a7c,
+    0x343cd6af, 0xf212c5be, 0xff1865cd, 0x03dcf3ca, 0xfe07c93a, 0x00487582, 0x001be9b7, 0xfff83b52,
+    0x338cb004, 0xf1ebe2ec, 0xff43ebac, 0x03cb9cf9, 0xfe08814e, 0x004b132b, 0x001abcd0, 0xfff86bf6,
+    0x32dc0d17, 0xf1c6a9c3, 0xff6f08e4, 0x03ba2398, 0xfe0965bc, 0x004d9dde, 0x0019939d, 0xfff89c60,
+    0x322af693, 0xf1a3181a, 0xff99badb, 0x03a889a1, 0xfe0a75da, 0x005015a5, 0x00186e31, 0xfff8cc86,
+    0x3179751f, 0xf1812bb0, 0xffc3ff0c, 0x0396d10c, 0xfe0bb0f9, 0x00527a8a, 0x00174c9c, 0xfff8fc62,
+    0x30c79163, 0xf160e22d, 0xffedd2fd, 0x0384fbd1, 0xfe0d166b, 0x0054cc9a, 0x00162eef, 0xfff92bec,
+    0x30155404, 0xf1423924, 0x00173447, 0x03730be0, 0xfe0ea57e, 0x00570be4, 0x00151538, 0xfff95b1e,
+    0x2f62c5a7, 0xf1252e0f, 0x00402092, 0x0361032a, 0xfe105d7e, 0x00593877, 0x0013ff88, 0xfff989ef,
+    0x2eafeeed, 0xf109be56, 0x00689598, 0x034ee39b, 0xfe123db6, 0x005b5267, 0x0012edea, 0xfff9b85b,
+    0x2dfcd873, 0xf0efe748, 0x0090911f, 0x033caf1d, 0xfe144570, 0x005d59c6, 0x0011e06d, 0xfff9e65a,
+    0x2d498ad3, 0xf0d7a622, 0x00b81102, 0x032a6796, 0xfe1673f2, 0x005f4eac, 0x0010d71d, 0xfffa13e5,
+    0x2c960ea3, 0xf0c0f808, 0x00df1328, 0x03180ee7, 0xfe18c884, 0x0061312e, 0x000fd205, 0xfffa40f8,
+    0x2be26c73, 0xf0abda0e, 0x0105958c, 0x0305a6f0, 0xfe1b4268, 0x00630167, 0x000ed130, 0xfffa6d8d,
+    0x2b2eaccf, 0xf0984931, 0x012b9635, 0x02f3318a, 0xfe1de0e2, 0x0064bf71, 0x000dd4a7, 0xfffa999d,
+    0x2a7ad83c, 0xf086425a, 0x0151133e, 0x02e0b08d, 0xfe20a335, 0x00666b68, 0x000cdc74, 0xfffac525,
+    0x29c6f738, 0xf075c260, 0x01760ad1, 0x02ce25ca, 0xfe2388a1, 0x0068056b, 0x000be89f, 0xfffaf01e,
+    0x2913123c, 0xf066c606, 0x019a7b27, 0x02bb9310, 0xfe269065, 0x00698d98, 0x000af931, 0xfffb1a84,
+    0x285f31b7, 0xf05949fb, 0x01be628c, 0x02a8fa2a, 0xfe29b9c1, 0x006b0411, 0x000a0e2f, 0xfffb4453,
+    0x27ab5e12, 0xf04d4ade, 0x01e1bf58, 0x02965cdb, 0xfe2d03f2, 0x006c68f8, 0x000927a0, 0xfffb6d86,
+    0x26f79fab, 0xf042c539, 0x02048ff8, 0x0283bce6, 0xfe306e35, 0x006dbc71, 0x00084589, 0xfffb961a,
+    0x2643feda, 0xf039b587, 0x0226d2e6, 0x02711c05, 0xfe33f7c7, 0x006efea0, 0x000767f0, 0xfffbbe09,
+    0x259083eb, 0xf032182f, 0x024886ad, 0x025e7bf0, 0xfe379fe3, 0x00702fae, 0x00068ed8, 0xfffbe552,
+    0x24dd3721, 0xf02be98a, 0x0269a9e9, 0x024bde5a, 0xfe3b65c4, 0x00714fc0, 0x0005ba46, 0xfffc0bef,
+    0x242a20b3, 0xf02725dc, 0x028a3b44, 0x023944ee, 0xfe3f48a5, 0x00725f02, 0x0004ea3a, 0xfffc31df,
+    0x237748cf, 0xf023c95d, 0x02aa397b, 0x0226b156, 0xfe4347c0, 0x00735d9c, 0x00041eb9, 0xfffc571e,
+    0x22c4b795, 0xf021d031, 0x02c9a359, 0x02142533, 0xfe476250, 0x00744bba, 0x000357c2, 0xfffc7ba9,
+    0x2212751a, 0xf0213671, 0x02e877b9, 0x0201a223, 0xfe4b978e, 0x0075298a, 0x00029558, 0xfffc9f7e,
+    0x21608968, 0xf021f823, 0x0306b586, 0x01ef29be, 0xfe4fe6b3, 0x0075f739, 0x0001d779, 0xfffcc29a,
+    0x20aefc79, 0xf0241140, 0x03245bbc, 0x01dcbd96, 0xfe544efb, 0x0076b4f5, 0x00011e26, 0xfffce4fc,
+    0x1ffdd63b, 0xf0277db1, 0x03416966, 0x01ca5f37, 0xfe58cf9d, 0x007762f0, 0x0000695e, 0xfffd06a1,
+    0x1f4d1e8e, 0xf02c3953, 0x035ddd9e, 0x01b81028, 0xfe5d67d4, 0x0078015a, 0xffffb91f, 0xfffd2787,
+    0x1e9cdd43, 0xf0323ff5, 0x0379b790, 0x01a5d1ea, 0xfe6216db, 0x00789065, 0xffff0d66, 0xfffd47ae,
+    0x1ded1a1d, 0xf0398d56, 0x0394f674, 0x0193a5f9, 0xfe66dbeb, 0x00791043, 0xfffe6631, 0xfffd6713,
diff --git a/services/audioflinger/AudioResamplerSincUp.h b/services/audioflinger/AudioResamplerSincUp.h
new file mode 100644
index 0000000..fd5367e
--- /dev/null
+++ b/services/audioflinger/AudioResamplerSincUp.h
@@ -0,0 +1,131 @@
+// cmd-line: fir -l 7 -s48000 -c 20478
+
+    0x6d374bc7, 0x111c6ba0, 0xf3240e61, 0x07d14a38, 0xfc509e64, 0x0139cee9, 0xffc8c866, 0xfffcc300,
+    0x6d35278a, 0x103e8192, 0xf36b9dfd, 0x07bdfaa5, 0xfc5102d0, 0x013d618d, 0xffc663b9, 0xfffd9592,
+    0x6d2ebafe, 0x0f62811a, 0xf3b3d8ac, 0x07a9f399, 0xfc51d9a6, 0x0140bea5, 0xffc41212, 0xfffe631e,
+    0x6d24069d, 0x0e8875ad, 0xf3fcb43e, 0x07953976, 0xfc53216f, 0x0143e67c, 0xffc1d373, 0xffff2b9f,
+    0x6d150b35, 0x0db06a89, 0xf4462690, 0x077fd0ac, 0xfc54d8ae, 0x0146d965, 0xffbfa7d9, 0xffffef10,
+    0x6d01c9e3, 0x0cda6ab5, 0xf4902587, 0x0769bdaf, 0xfc56fdda, 0x014997bb, 0xffbd8f40, 0x0000ad6e,
+    0x6cea4418, 0x0c0680fe, 0xf4daa718, 0x07530501, 0xfc598f60, 0x014c21db, 0xffbb89a1, 0x000166b6,
+    0x6cce7b97, 0x0b34b7f5, 0xf525a143, 0x073bab28, 0xfc5c8ba5, 0x014e782a, 0xffb996f3, 0x00021ae5,
+    0x6cae7272, 0x0a6519f4, 0xf5710a17, 0x0723b4b4, 0xfc5ff105, 0x01509b14, 0xffb7b728, 0x0002c9fd,
+    0x6c8a2b0f, 0x0997b116, 0xf5bcd7b1, 0x070b2639, 0xfc63bdd3, 0x01528b08, 0xffb5ea31, 0x000373fb,
+    0x6c61a823, 0x08cc873c, 0xf609003f, 0x06f20453, 0xfc67f05a, 0x0154487b, 0xffb42ffc, 0x000418e2,
+    0x6c34ecb5, 0x0803a60a, 0xf6557a00, 0x06d853a2, 0xfc6c86dd, 0x0155d3e8, 0xffb28876, 0x0004b8b3,
+    0x6c03fc1c, 0x073d16e7, 0xf6a23b44, 0x06be18cd, 0xfc717f97, 0x01572dcf, 0xffb0f388, 0x00055371,
+    0x6bced9ff, 0x0678e2fc, 0xf6ef3a6e, 0x06a3587e, 0xfc76d8bc, 0x015856b6, 0xffaf7118, 0x0005e921,
+    0x6b958a54, 0x05b71332, 0xf73c6df4, 0x06881761, 0xfc7c9079, 0x01594f25, 0xffae010b, 0x000679c5,
+    0x6b581163, 0x04f7b037, 0xf789cc61, 0x066c5a27, 0xfc82a4f4, 0x015a17ab, 0xffaca344, 0x00070564,
+    0x6b1673c1, 0x043ac276, 0xf7d74c53, 0x06502583, 0xfc89144d, 0x015ab0db, 0xffab57a1, 0x00078c04,
+    0x6ad0b652, 0x0380521c, 0xf824e480, 0x06337e2a, 0xfc8fdc9f, 0x015b1b4e, 0xffaa1e02, 0x00080dab,
+    0x6a86de48, 0x02c86715, 0xf8728bb3, 0x061668d2, 0xfc96fbfc, 0x015b579e, 0xffa8f641, 0x00088a62,
+    0x6a38f123, 0x0213090c, 0xf8c038d0, 0x05f8ea30, 0xfc9e7074, 0x015b666c, 0xffa7e039, 0x00090230,
+    0x69e6f4b1, 0x01603f6e, 0xf90de2d1, 0x05db06fc, 0xfca63810, 0x015b485b, 0xffa6dbc0, 0x0009751e,
+    0x6990ef0b, 0x00b01162, 0xf95b80cb, 0x05bcc3ed, 0xfcae50d6, 0x015afe14, 0xffa5e8ad, 0x0009e337,
+    0x6936e697, 0x000285d0, 0xf9a909ea, 0x059e25b5, 0xfcb6b8c4, 0x015a8843, 0xffa506d2, 0x000a4c85,
+    0x68d8e206, 0xff57a35e, 0xf9f67577, 0x057f310a, 0xfcbf6dd8, 0x0159e796, 0xffa43603, 0x000ab112,
+    0x6876e855, 0xfeaf706f, 0xfa43bad2, 0x055fea9d, 0xfcc86e09, 0x01591cc0, 0xffa3760e, 0x000b10ec,
+    0x681100c9, 0xfe09f323, 0xfa90d17b, 0x0540571a, 0xfcd1b74c, 0x01582878, 0xffa2c6c2, 0x000b6c1d,
+    0x67a732f4, 0xfd673159, 0xfaddb10c, 0x05207b2f, 0xfcdb4793, 0x01570b77, 0xffa227ec, 0x000bc2b3,
+    0x673986ac, 0xfcc730aa, 0xfb2a513b, 0x05005b82, 0xfce51ccb, 0x0155c678, 0xffa19957, 0x000c14bb,
+    0x66c80413, 0xfc29f670, 0xfb76a9dd, 0x04dffcb6, 0xfcef34e1, 0x01545a3c, 0xffa11acb, 0x000c6244,
+    0x6652b392, 0xfb8f87bd, 0xfbc2b2e4, 0x04bf6369, 0xfcf98dbe, 0x0152c783, 0xffa0ac11, 0x000cab5c,
+    0x65d99dd5, 0xfaf7e963, 0xfc0e6461, 0x049e9433, 0xfd04254a, 0x01510f13, 0xffa04cf0, 0x000cf012,
+    0x655ccbd3, 0xfa631fef, 0xfc59b685, 0x047d93a8, 0xfd0ef969, 0x014f31b2, 0xff9ffd2c, 0x000d3075,
+    0x64dc46c3, 0xf9d12fab, 0xfca4a19f, 0x045c6654, 0xfd1a0801, 0x014d3029, 0xff9fbc89, 0x000d6c97,
+    0x64581823, 0xf9421c9d, 0xfcef1e20, 0x043b10bd, 0xfd254ef4, 0x014b0b45, 0xff9f8ac9, 0x000da486,
+    0x63d049b4, 0xf8b5ea87, 0xfd392498, 0x04199760, 0xfd30cc24, 0x0148c3d2, 0xff9f67ae, 0x000dd854,
+    0x6344e578, 0xf82c9ce7, 0xfd82adba, 0x03f7feb4, 0xfd3c7d73, 0x01465a9f, 0xff9f52f7, 0x000e0812,
+    0x62b5f5b2, 0xf7a636fa, 0xfdcbb25a, 0x03d64b27, 0xfd4860c2, 0x0143d07f, 0xff9f4c65, 0x000e33d3,
+    0x622384e8, 0xf722bbb5, 0xfe142b6e, 0x03b4811d, 0xfd5473f3, 0x01412643, 0xff9f53b4, 0x000e5ba7,
+    0x618d9ddc, 0xf6a22dcf, 0xfe5c120f, 0x0392a4f4, 0xfd60b4e7, 0x013e5cc0, 0xff9f68a1, 0x000e7fa1,
+    0x60f44b91, 0xf6248fb6, 0xfea35f79, 0x0370bafc, 0xfd6d2180, 0x013b74ca, 0xff9f8ae9, 0x000e9fd5,
+    0x60579947, 0xf5a9e398, 0xfeea0d0c, 0x034ec77f, 0xfd79b7a1, 0x01386f3a, 0xff9fba47, 0x000ebc54,
+    0x5fb79278, 0xf5322b61, 0xff30144a, 0x032ccebb, 0xfd86752e, 0x01354ce7, 0xff9ff674, 0x000ed533,
+    0x5f1442dc, 0xf4bd68b6, 0xff756edc, 0x030ad4e1, 0xfd93580d, 0x01320ea9, 0xffa03f2b, 0x000eea84,
+    0x5e6db665, 0xf44b9cfe, 0xffba168d, 0x02e8de19, 0xfda05e23, 0x012eb55a, 0xffa09425, 0x000efc5c,
+    0x5dc3f93c, 0xf3dcc959, 0xfffe054e, 0x02c6ee7f, 0xfdad855b, 0x012b41d3, 0xffa0f519, 0x000f0ace,
+    0x5d1717c4, 0xf370eea9, 0x00413536, 0x02a50a22, 0xfdbacb9e, 0x0127b4f1, 0xffa161bf, 0x000f15ef,
+    0x5c671e96, 0xf3080d8c, 0x0083a081, 0x02833506, 0xfdc82edb, 0x01240f8e, 0xffa1d9cf, 0x000f1dd2,
+    0x5bb41a80, 0xf2a2265e, 0x00c54190, 0x02617321, 0xfdd5ad01, 0x01205285, 0xffa25cfe, 0x000f228d,
+    0x5afe1886, 0xf23f393b, 0x010612eb, 0x023fc85c, 0xfde34403, 0x011c7eb2, 0xffa2eb04, 0x000f2434,
+    0x5a4525df, 0xf1df45fd, 0x01460f41, 0x021e3891, 0xfdf0f1d6, 0x011894f0, 0xffa38395, 0x000f22dc,
+    0x59894ff3, 0xf1824c3e, 0x01853165, 0x01fcc78f, 0xfdfeb475, 0x0114961b, 0xffa42668, 0x000f1e99,
+    0x58caa45b, 0xf1284b58, 0x01c37452, 0x01db7914, 0xfe0c89db, 0x0110830f, 0xffa4d332, 0x000f1781,
+    0x580930e1, 0xf0d14267, 0x0200d32c, 0x01ba50d2, 0xfe1a7009, 0x010c5ca6, 0xffa589a6, 0x000f0da8,
+    0x5745037c, 0xf07d3043, 0x023d493c, 0x0199526b, 0xfe286505, 0x010823ba, 0xffa6497c, 0x000f0125,
+    0x567e2a51, 0xf02c138a, 0x0278d1f2, 0x01788170, 0xfe3666d5, 0x0103d927, 0xffa71266, 0x000ef20b,
+    0x55b4b3af, 0xefddea9a, 0x02b368e6, 0x0157e166, 0xfe447389, 0x00ff7dc4, 0xffa7e41a, 0x000ee070,
+    0x54e8ae13, 0xef92b393, 0x02ed09d7, 0x013775bf, 0xfe528931, 0x00fb126b, 0xffa8be4c, 0x000ecc69,
+    0x541a281e, 0xef4a6c58, 0x0325b0ad, 0x011741df, 0xfe60a5e5, 0x00f697f3, 0xffa9a0b1, 0x000eb60b,
+    0x5349309e, 0xef051290, 0x035d5977, 0x00f7491a, 0xfe6ec7c0, 0x00f20f32, 0xffaa8afe, 0x000e9d6b,
+    0x5275d684, 0xeec2a3a3, 0x0394006a, 0x00d78eb3, 0xfe7cece2, 0x00ed78ff, 0xffab7ce7, 0x000e829e,
+    0x51a028e8, 0xee831cc3, 0x03c9a1e5, 0x00b815da, 0xfe8b1373, 0x00e8d62d, 0xffac7621, 0x000e65ba,
+    0x50c83704, 0xee467ae1, 0x03fe3a6f, 0x0098e1b3, 0xfe99399f, 0x00e4278f, 0xffad7662, 0x000e46d3,
+    0x4fee1037, 0xee0cbab9, 0x0431c6b5, 0x0079f54c, 0xfea75d97, 0x00df6df7, 0xffae7d5f, 0x000e25fd,
+    0x4f11c3fe, 0xedd5d8ca, 0x0464438c, 0x005b53a4, 0xfeb57d92, 0x00daaa34, 0xffaf8acd, 0x000e034f,
+    0x4e3361f7, 0xeda1d15c, 0x0495adf2, 0x003cffa9, 0xfec397cf, 0x00d5dd16, 0xffb09e63, 0x000ddedb,
+    0x4d52f9df, 0xed70a07d, 0x04c6030d, 0x001efc35, 0xfed1aa92, 0x00d10769, 0xffb1b7d8, 0x000db8b7,
+    0x4c709b8e, 0xed424205, 0x04f54029, 0x00014c12, 0xfedfb425, 0x00cc29f7, 0xffb2d6e1, 0x000d90f6,
+    0x4b8c56f8, 0xed16b196, 0x052362ba, 0xffe3f1f7, 0xfeedb2da, 0x00c7458a, 0xffb3fb37, 0x000d67ae,
+    0x4aa63c2c, 0xecedea99, 0x0550685d, 0xffc6f08a, 0xfefba508, 0x00c25ae8, 0xffb52490, 0x000d3cf1,
+    0x49be5b50, 0xecc7e845, 0x057c4ed4, 0xffaa4a5d, 0xff09890f, 0x00bd6ad7, 0xffb652a7, 0x000d10d5,
+    0x48d4c4a2, 0xeca4a59b, 0x05a7140b, 0xff8e01f1, 0xff175d53, 0x00b87619, 0xffb78533, 0x000ce36b,
+    0x47e98874, 0xec841d68, 0x05d0b612, 0xff7219b3, 0xff252042, 0x00b37d70, 0xffb8bbed, 0x000cb4c8,
+    0x46fcb72d, 0xec664a48, 0x05f93324, 0xff5693fe, 0xff32d04f, 0x00ae8198, 0xffb9f691, 0x000c84ff,
+    0x460e6148, 0xec4b26a2, 0x0620899e, 0xff3b731b, 0xff406bf8, 0x00a9834e, 0xffbb34d8, 0x000c5422,
+    0x451e9750, 0xec32acb0, 0x0646b808, 0xff20b93e, 0xff4df1be, 0x00a4834c, 0xffbc767f, 0x000c2245,
+    0x442d69de, 0xec1cd677, 0x066bbd0d, 0xff066889, 0xff5b602c, 0x009f8249, 0xffbdbb42, 0x000bef79,
+    0x433ae99c, 0xec099dcf, 0x068f9781, 0xfeec830d, 0xff68b5d5, 0x009a80f8, 0xffbf02dd, 0x000bbbd2,
+    0x4247273f, 0xebf8fc64, 0x06b2465b, 0xfed30ac5, 0xff75f153, 0x0095800c, 0xffc04d0f, 0x000b8760,
+    0x41523389, 0xebeaebaf, 0x06d3c8bb, 0xfeba0199, 0xff831148, 0x00908034, 0xffc19996, 0x000b5235,
+    0x405c1f43, 0xebdf6500, 0x06f41de3, 0xfea16960, 0xff90145e, 0x008b821b, 0xffc2e832, 0x000b1c64,
+    0x3f64fb40, 0xebd6617b, 0x0713453d, 0xfe8943dc, 0xff9cf947, 0x0086866b, 0xffc438a3, 0x000ae5fc,
+    0x3e6cd85b, 0xebcfda19, 0x07313e56, 0xfe7192bd, 0xffa9bebe, 0x00818dcb, 0xffc58aaa, 0x000aaf0f,
+    0x3d73c772, 0xebcbc7a7, 0x074e08e0, 0xfe5a579d, 0xffb66386, 0x007c98de, 0xffc6de09, 0x000a77ac,
+    0x3c79d968, 0xebca22cc, 0x0769a4b2, 0xfe439407, 0xffc2e669, 0x0077a845, 0xffc83285, 0x000a3fe5,
+    0x3b7f1f23, 0xebcae405, 0x078411c7, 0xfe2d496f, 0xffcf463a, 0x0072bc9d, 0xffc987e0, 0x000a07c9,
+    0x3a83a989, 0xebce03aa, 0x079d503b, 0xfe177937, 0xffdb81d6, 0x006dd680, 0xffcadde1, 0x0009cf67,
+    0x3987897f, 0xebd379eb, 0x07b56051, 0xfe0224b0, 0xffe79820, 0x0068f687, 0xffcc344c, 0x000996ce,
+    0x388acfe9, 0xebdb3ed5, 0x07cc426c, 0xfded4d13, 0xfff38806, 0x00641d44, 0xffcd8aeb, 0x00095e0e,
+    0x378d8da8, 0xebe54a4f, 0x07e1f712, 0xfdd8f38b, 0xffff507b, 0x005f4b4a, 0xffcee183, 0x00092535,
+    0x368fd397, 0xebf1941f, 0x07f67eec, 0xfdc5192d, 0x000af07f, 0x005a8125, 0xffd037e0, 0x0008ec50,
+    0x3591b28b, 0xec0013e8, 0x0809dac3, 0xfdb1befc, 0x00166718, 0x0055bf60, 0xffd18dcc, 0x0008b36e,
+    0x34933b50, 0xec10c12c, 0x081c0b84, 0xfd9ee5e7, 0x0021b355, 0x00510682, 0xffd2e311, 0x00087a9c,
+    0x33947eab, 0xec23934f, 0x082d1239, 0xfd8c8ecc, 0x002cd44d, 0x004c570f, 0xffd4377d, 0x000841e8,
+    0x32958d55, 0xec388194, 0x083cf010, 0xfd7aba74, 0x0037c922, 0x0047b186, 0xffd58ade, 0x0008095d,
+    0x319677fa, 0xec4f8322, 0x084ba654, 0xfd696998, 0x004290fc, 0x00431666, 0xffd6dd02, 0x0007d108,
+    0x30974f3b, 0xec688f02, 0x08593671, 0xfd589cdc, 0x004d2b0e, 0x003e8628, 0xffd82dba, 0x000798f5,
+    0x2f9823a8, 0xec839c22, 0x0865a1f1, 0xfd4854d3, 0x00579691, 0x003a0141, 0xffd97cd6, 0x00076130,
+    0x2e9905c1, 0xeca0a156, 0x0870ea7e, 0xfd3891fd, 0x0061d2ca, 0x00358824, 0xffdaca2a, 0x000729c4,
+    0x2d9a05f4, 0xecbf9558, 0x087b11de, 0xfd2954c8, 0x006bdf05, 0x00311b41, 0xffdc1588, 0x0006f2bb,
+    0x2c9b349e, 0xece06ecb, 0x088419f6, 0xfd1a9d91, 0x0075ba95, 0x002cbb03, 0xffdd5ec6, 0x0006bc21,
+    0x2b9ca203, 0xed032439, 0x088c04c8, 0xfd0c6ca2, 0x007f64da, 0x002867d2, 0xffdea5bb, 0x000685ff,
+    0x2a9e5e57, 0xed27ac16, 0x0892d470, 0xfcfec233, 0x0088dd38, 0x00242213, 0xffdfea3c, 0x0006505f,
+    0x29a079b2, 0xed4dfcc2, 0x08988b2a, 0xfcf19e6b, 0x0092231e, 0x001fea27, 0xffe12c22, 0x00061b4b,
+    0x28a30416, 0xed760c88, 0x089d2b4a, 0xfce50161, 0x009b3605, 0x001bc06b, 0xffe26b48, 0x0005e6cb,
+    0x27a60d6a, 0xed9fd1a2, 0x08a0b740, 0xfcd8eb17, 0x00a4156b, 0x0017a53b, 0xffe3a788, 0x0005b2e8,
+    0x26a9a57b, 0xedcb4237, 0x08a33196, 0xfccd5b82, 0x00acc0da, 0x001398ec, 0xffe4e0bf, 0x00057faa,
+    0x25addbf9, 0xedf8545b, 0x08a49cf0, 0xfcc25285, 0x00b537e1, 0x000f9bd2, 0xffe616c8, 0x00054d1a,
+    0x24b2c075, 0xee26fe17, 0x08a4fc0d, 0xfcb7cff0, 0x00bd7a1c, 0x000bae3c, 0xffe74984, 0x00051b3e,
+    0x23b86263, 0xee573562, 0x08a451c0, 0xfcadd386, 0x00c5872a, 0x0007d075, 0xffe878d3, 0x0004ea1d,
+    0x22bed116, 0xee88f026, 0x08a2a0f8, 0xfca45cf7, 0x00cd5eb7, 0x000402c8, 0xffe9a494, 0x0004b9c0,
+    0x21c61bc0, 0xeebc2444, 0x089fecbb, 0xfc9b6be5, 0x00d50075, 0x00004579, 0xffeaccaa, 0x00048a2b,
+    0x20ce516f, 0xeef0c78d, 0x089c3824, 0xfc92ffe1, 0x00dc6c1e, 0xfffc98c9, 0xffebf0fa, 0x00045b65,
+    0x1fd7810f, 0xef26cfca, 0x08978666, 0xfc8b186d, 0x00e3a175, 0xfff8fcf7, 0xffed1166, 0x00042d74,
+    0x1ee1b965, 0xef5e32bd, 0x0891dac8, 0xfc83b4fc, 0x00eaa045, 0xfff5723d, 0xffee2dd7, 0x0004005e,
+    0x1ded0911, 0xef96e61c, 0x088b38a9, 0xfc7cd4f0, 0x00f16861, 0xfff1f8d2, 0xffef4632, 0x0003d426,
+    0x1cf97e8b, 0xefd0df9a, 0x0883a378, 0xfc76779e, 0x00f7f9a3, 0xffee90eb, 0xfff05a60, 0x0003a8d2,
+    0x1c072823, 0xf00c14e1, 0x087b1ebc, 0xfc709c4d, 0x00fe53ef, 0xffeb3ab8, 0xfff16a4a, 0x00037e65,
+    0x1b1613ff, 0xf0487b98, 0x0871ae0d, 0xfc6b4233, 0x0104772e, 0xffe7f666, 0xfff275db, 0x000354e5,
+    0x1a26501b, 0xf0860962, 0x08675516, 0xfc66687a, 0x010a6353, 0xffe4c41e, 0xfff37d00, 0x00032c54,
+    0x1937ea47, 0xf0c4b3e0, 0x085c1794, 0xfc620e3d, 0x01101858, 0xffe1a408, 0xfff47fa5, 0x000304b7,
+    0x184af025, 0xf10470b0, 0x084ff957, 0xfc5e328c, 0x0115963d, 0xffde9646, 0xfff57db8, 0x0002de0e,
+    0x175f6f2b, 0xf1453571, 0x0842fe3d, 0xfc5ad465, 0x011add0b, 0xffdb9af8, 0xfff67729, 0x0002b85f,
+    0x1675749e, 0xf186f7c0, 0x08352a35, 0xfc57f2be, 0x011fecd3, 0xffd8b23b, 0xfff76be9, 0x000293aa,
+    0x158d0d95, 0xf1c9ad40, 0x0826813e, 0xfc558c7c, 0x0124c5ab, 0xffd5dc28, 0xfff85be8, 0x00026ff2,
+    0x14a646f6, 0xf20d4b92, 0x08170767, 0xfc53a07b, 0x012967b1, 0xffd318d6, 0xfff9471b, 0x00024d39,
+    0x13c12d73, 0xf251c85d, 0x0806c0cb, 0xfc522d88, 0x012dd30a, 0xffd06858, 0xfffa2d74, 0x00022b7f,
+    0x12ddcd8f, 0xf297194d, 0x07f5b193, 0xfc513266, 0x013207e4, 0xffcdcabe, 0xfffb0ee9, 0x00020ac7,
+    0x11fc3395, 0xf2dd3411, 0x07e3ddf7, 0xfc50adcc, 0x01360670, 0xffcb4014, 0xfffbeb70, 0x0001eb10,
+    0x111c6ba0, 0xf3240e61, 0x07d14a38, 0xfc509e64, 0x0139cee9, 0xffc8c866, 0xfffcc300, 0x0001cc5c,
diff --git a/services/audioflinger/Configuration.h b/services/audioflinger/Configuration.h
index 6a8aeb1..845697a 100644
--- a/services/audioflinger/Configuration.h
+++ b/services/audioflinger/Configuration.h
@@ -29,9 +29,8 @@
 // uncomment to display CPU load adjusted for CPU frequency
 //#define CPU_FREQUENCY_STATISTICS
 
-// uncomment to enable fast mixer to take performance samples for later statistical analysis
-#define FAST_MIXER_STATISTICS
-// FIXME rename to FAST_THREAD_STATISTICS
+// uncomment to enable fast threads to take performance samples for later statistical analysis
+#define FAST_THREAD_STATISTICS
 
 // uncomment for debugging timing problems related to StateQueue::push()
 //#define STATE_QUEUE_DUMP
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index bcaf8ae..8bccb47 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1953,4 +1953,4 @@
     }
 }
 
-}; // namespace android
+} // namespace android
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/FastCapture.cpp
index 0c9b976..9e7e8a4 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/FastCapture.cpp
@@ -29,18 +29,18 @@
 
 namespace android {
 
-/*static*/ const FastCaptureState FastCapture::initial;
+/*static*/ const FastCaptureState FastCapture::sInitial;
 
 FastCapture::FastCapture() : FastThread(),
-    inputSource(NULL), inputSourceGen(0), pipeSink(NULL), pipeSinkGen(0),
-    readBuffer(NULL), readBufferState(-1), format(Format_Invalid), sampleRate(0),
-    // dummyDumpState
-    totalNativeFramesRead(0)
+    mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0),
+    mReadBuffer(NULL), mReadBufferState(-1), mFormat(Format_Invalid), mSampleRate(0),
+    // mDummyDumpState
+    mTotalNativeFramesRead(0)
 {
-    previous = &initial;
-    current = &initial;
+    mPrevious = &sInitial;
+    mCurrent = &sInitial;
 
-    mDummyDumpState = &dummyDumpState;
+    mDummyDumpState = &mDummyFastCaptureDumpState;
 }
 
 FastCapture::~FastCapture()
@@ -63,13 +63,13 @@
 
 void FastCapture::onIdle()
 {
-    preIdle = *(const FastCaptureState *)current;
-    current = &preIdle;
+    mPreIdle = *(const FastCaptureState *)mCurrent;
+    mCurrent = &mPreIdle;
 }
 
 void FastCapture::onExit()
 {
-    delete[] readBuffer;
+    free(mReadBuffer);
 }
 
 bool FastCapture::isSubClassCommand(FastThreadState::Command command)
@@ -86,67 +86,67 @@
 
 void FastCapture::onStateChange()
 {
-    const FastCaptureState * const current = (const FastCaptureState *) this->current;
-    const FastCaptureState * const previous = (const FastCaptureState *) this->previous;
-    FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) this->dumpState;
+    const FastCaptureState * const current = (const FastCaptureState *) mCurrent;
+    const FastCaptureState * const previous = (const FastCaptureState *) mPrevious;
+    FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) mDumpState;
     const size_t frameCount = current->mFrameCount;
 
     bool eitherChanged = false;
 
     // check for change in input HAL configuration
-    NBAIO_Format previousFormat = format;
-    if (current->mInputSourceGen != inputSourceGen) {
-        inputSource = current->mInputSource;
-        inputSourceGen = current->mInputSourceGen;
-        if (inputSource == NULL) {
-            format = Format_Invalid;
-            sampleRate = 0;
+    NBAIO_Format previousFormat = mFormat;
+    if (current->mInputSourceGen != mInputSourceGen) {
+        mInputSource = current->mInputSource;
+        mInputSourceGen = current->mInputSourceGen;
+        if (mInputSource == NULL) {
+            mFormat = Format_Invalid;
+            mSampleRate = 0;
         } else {
-            format = inputSource->format();
-            sampleRate = Format_sampleRate(format);
-            unsigned channelCount = Format_channelCount(format);
+            mFormat = mInputSource->format();
+            mSampleRate = Format_sampleRate(mFormat);
+            unsigned channelCount = Format_channelCount(mFormat);
             ALOG_ASSERT(channelCount == 1 || channelCount == 2);
         }
-        dumpState->mSampleRate = sampleRate;
+        dumpState->mSampleRate = mSampleRate;
         eitherChanged = true;
     }
 
     // check for change in pipe
-    if (current->mPipeSinkGen != pipeSinkGen) {
-        pipeSink = current->mPipeSink;
-        pipeSinkGen = current->mPipeSinkGen;
+    if (current->mPipeSinkGen != mPipeSinkGen) {
+        mPipeSink = current->mPipeSink;
+        mPipeSinkGen = current->mPipeSinkGen;
         eitherChanged = true;
     }
 
     // input source and pipe sink must be compatible
-    if (eitherChanged && inputSource != NULL && pipeSink != NULL) {
-        ALOG_ASSERT(Format_isEqual(format, pipeSink->format()));
+    if (eitherChanged && mInputSource != NULL && mPipeSink != NULL) {
+        ALOG_ASSERT(Format_isEqual(mFormat, mPipeSink->format()));
     }
 
-    if ((!Format_isEqual(format, previousFormat)) || (frameCount != previous->mFrameCount)) {
-        // FIXME to avoid priority inversion, don't delete here
-        delete[] readBuffer;
-        readBuffer = NULL;
-        if (frameCount > 0 && sampleRate > 0) {
+    if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
+        // FIXME to avoid priority inversion, don't free here
+        free(mReadBuffer);
+        mReadBuffer = NULL;
+        if (frameCount > 0 && mSampleRate > 0) {
             // FIXME new may block for unbounded time at internal mutex of the heap
             //       implementation; it would be better to have normal capture thread allocate for
             //       us to avoid blocking here and to prevent possible priority inversion
-            unsigned channelCount = Format_channelCount(format);
-            // FIXME frameSize
-            readBuffer = new short[frameCount * channelCount];
-            periodNs = (frameCount * 1000000000LL) / sampleRate;    // 1.00
-            underrunNs = (frameCount * 1750000000LL) / sampleRate;  // 1.75
-            overrunNs = (frameCount * 500000000LL) / sampleRate;    // 0.50
-            forceNs = (frameCount * 950000000LL) / sampleRate;      // 0.95
-            warmupNs = (frameCount * 500000000LL) / sampleRate;     // 0.50
+            (void)posix_memalign(&mReadBuffer, 32, frameCount * Format_frameSize(mFormat));
+            mPeriodNs = (frameCount * 1000000000LL) / mSampleRate;      // 1.00
+            mUnderrunNs = (frameCount * 1750000000LL) / mSampleRate;    // 1.75
+            mOverrunNs = (frameCount * 500000000LL) / mSampleRate;      // 0.50
+            mForceNs = (frameCount * 950000000LL) / mSampleRate;        // 0.95
+            mWarmupNsMin = (frameCount * 750000000LL) / mSampleRate;    // 0.75
+            mWarmupNsMax = (frameCount * 1250000000LL) / mSampleRate;   // 1.25
         } else {
-            periodNs = 0;
-            underrunNs = 0;
-            overrunNs = 0;
-            forceNs = 0;
-            warmupNs = 0;
+            mPeriodNs = 0;
+            mUnderrunNs = 0;
+            mOverrunNs = 0;
+            mForceNs = 0;
+            mWarmupNsMin = 0;
+            mWarmupNsMax = LONG_MAX;
         }
-        readBufferState = -1;
+        mReadBufferState = -1;
         dumpState->mFrameCount = frameCount;
     }
 
@@ -154,44 +154,43 @@
 
 void FastCapture::onWork()
 {
-    const FastCaptureState * const current = (const FastCaptureState *) this->current;
-    FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) this->dumpState;
-    const FastCaptureState::Command command = this->command;
+    const FastCaptureState * const current = (const FastCaptureState *) mCurrent;
+    FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) mDumpState;
+    const FastCaptureState::Command command = mCommand;
     const size_t frameCount = current->mFrameCount;
 
     if ((command & FastCaptureState::READ) /*&& isWarm*/) {
-        ALOG_ASSERT(inputSource != NULL);
-        ALOG_ASSERT(readBuffer != NULL);
+        ALOG_ASSERT(mInputSource != NULL);
+        ALOG_ASSERT(mReadBuffer != NULL);
         dumpState->mReadSequence++;
         ATRACE_BEGIN("read");
-        ssize_t framesRead = inputSource->read(readBuffer, frameCount,
+        ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount,
                 AudioBufferProvider::kInvalidPTS);
         ATRACE_END();
         dumpState->mReadSequence++;
         if (framesRead >= 0) {
             LOG_ALWAYS_FATAL_IF((size_t) framesRead > frameCount);
-            totalNativeFramesRead += framesRead;
-            dumpState->mFramesRead = totalNativeFramesRead;
-            readBufferState = framesRead;
+            mTotalNativeFramesRead += framesRead;
+            dumpState->mFramesRead = mTotalNativeFramesRead;
+            mReadBufferState = framesRead;
         } else {
             dumpState->mReadErrors++;
-            readBufferState = 0;
+            mReadBufferState = 0;
         }
         // FIXME rename to attemptedIO
-        attemptedWrite = true;
+        mAttemptedWrite = true;
     }
 
     if (command & FastCaptureState::WRITE) {
-        ALOG_ASSERT(pipeSink != NULL);
-        ALOG_ASSERT(readBuffer != NULL);
-        if (readBufferState < 0) {
-            unsigned channelCount = Format_channelCount(format);
-            // FIXME frameSize
-            memset(readBuffer, 0, frameCount * channelCount * sizeof(short));
-            readBufferState = frameCount;
+        ALOG_ASSERT(mPipeSink != NULL);
+        ALOG_ASSERT(mReadBuffer != NULL);
+        if (mReadBufferState < 0) {
+            unsigned channelCount = Format_channelCount(mFormat);
+            memset(mReadBuffer, 0, frameCount * Format_frameSize(mFormat));
+            mReadBufferState = frameCount;
         }
-        if (readBufferState > 0) {
-            ssize_t framesWritten = pipeSink->write(readBuffer, readBufferState);
+        if (mReadBufferState > 0) {
+            ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState);
             // FIXME This supports at most one fast capture client.
             //       To handle multiple clients this could be converted to an array,
             //       or with a lot more work the control block could be shared by all clients.
@@ -210,13 +209,4 @@
     }
 }
 
-FastCaptureDumpState::FastCaptureDumpState() : FastThreadDumpState(),
-    mReadSequence(0), mFramesRead(0), mReadErrors(0), mSampleRate(0), mFrameCount(0)
-{
-}
-
-FastCaptureDumpState::~FastCaptureDumpState()
-{
-}
-
 }   // namespace android
diff --git a/services/audioflinger/FastCapture.h b/services/audioflinger/FastCapture.h
index e535b9d..e258a4d 100644
--- a/services/audioflinger/FastCapture.h
+++ b/services/audioflinger/FastCapture.h
@@ -20,23 +20,12 @@
 #include "FastThread.h"
 #include "StateQueue.h"
 #include "FastCaptureState.h"
+#include "FastCaptureDumpState.h"
 
 namespace android {
 
 typedef StateQueue<FastCaptureState> FastCaptureStateQueue;
 
-struct FastCaptureDumpState : FastThreadDumpState {
-    FastCaptureDumpState();
-    /*virtual*/ ~FastCaptureDumpState();
-
-    // FIXME by renaming, could pull up many of these to FastThreadDumpState
-    uint32_t mReadSequence;     // incremented before and after each read()
-    uint32_t mFramesRead;       // total number of frames read successfully
-    uint32_t mReadErrors;       // total number of read() errors
-    uint32_t mSampleRate;
-    size_t   mFrameCount;
-};
-
 class FastCapture : public FastThread {
 
 public:
@@ -57,19 +46,21 @@
     virtual void onStateChange();
     virtual void onWork();
 
-    static const FastCaptureState initial;
-    FastCaptureState preIdle; // copy of state before we went into idle
+    static const FastCaptureState sInitial;
+
+    FastCaptureState    mPreIdle;   // copy of state before we went into idle
     // FIXME by renaming, could pull up many of these to FastThread
-    NBAIO_Source *inputSource;
-    int inputSourceGen;
-    NBAIO_Sink *pipeSink;
-    int pipeSinkGen;
-    short *readBuffer;
-    ssize_t readBufferState;    // number of initialized frames in readBuffer, or -1 to clear
-    NBAIO_Format format;
-    unsigned sampleRate;
-    FastCaptureDumpState dummyDumpState;
-    uint32_t totalNativeFramesRead; // copied to dumpState->mFramesRead
+    NBAIO_Source*       mInputSource;
+    int                 mInputSourceGen;
+    NBAIO_Sink*         mPipeSink;
+    int                 mPipeSinkGen;
+    void*               mReadBuffer;
+    ssize_t             mReadBufferState;   // number of initialized frames in readBuffer,
+                                            // or -1 to clear
+    NBAIO_Format        mFormat;
+    unsigned            mSampleRate;
+    FastCaptureDumpState mDummyFastCaptureDumpState;
+    uint32_t            mTotalNativeFramesRead; // copied to dumpState->mFramesRead
 
 };  // class FastCapture
 
diff --git a/services/audioflinger/FastCaptureDumpState.cpp b/services/audioflinger/FastCaptureDumpState.cpp
new file mode 100644
index 0000000..53eeba5
--- /dev/null
+++ b/services/audioflinger/FastCaptureDumpState.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 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 "FastCaptureDumpState"
+//define LOG_NDEBUG 0
+
+#include "Configuration.h"
+#include <utils/Log.h>
+#include "FastCaptureDumpState.h"
+#include "FastCaptureState.h"
+
+namespace android {
+
+FastCaptureDumpState::FastCaptureDumpState() : FastThreadDumpState(),
+    mReadSequence(0), mFramesRead(0), mReadErrors(0), mSampleRate(0), mFrameCount(0)
+{
+}
+
+FastCaptureDumpState::~FastCaptureDumpState()
+{
+}
+
+void FastCaptureDumpState::dump(int fd) const
+{
+    if (mCommand == FastCaptureState::INITIAL) {
+        dprintf(fd, "  FastCapture not initialized\n");
+        return;
+    }
+    double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+            (mMeasuredWarmupTs.tv_nsec / 1000000.0);
+    double periodSec = (double) mFrameCount / mSampleRate;
+    dprintf(fd, "  FastCapture command=%s readSequence=%u framesRead=%u\n"
+                "              readErrors=%u sampleRate=%u frameCount=%zu\n"
+                "              measuredWarmup=%.3g ms, warmupCycles=%u period=%.2f ms\n",
+                FastCaptureState::commandToString(mCommand), mReadSequence, mFramesRead,
+                mReadErrors, mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles,
+                periodSec * 1e3);
+}
+
+}   // android
diff --git a/services/audioflinger/FastCaptureDumpState.h b/services/audioflinger/FastCaptureDumpState.h
new file mode 100644
index 0000000..6f9c4c3
--- /dev/null
+++ b/services/audioflinger/FastCaptureDumpState.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 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_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+#define ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+
+#include <stdint.h>
+#include "Configuration.h"
+#include "FastThreadDumpState.h"
+
+namespace android {
+
+struct FastCaptureDumpState : FastThreadDumpState {
+    FastCaptureDumpState();
+    /*virtual*/ ~FastCaptureDumpState();
+
+    void dump(int fd) const;    // should only be called on a stable copy, not the original
+
+    // FIXME by renaming, could pull up many of these to FastThreadDumpState
+    uint32_t mReadSequence;     // incremented before and after each read()
+    uint32_t mFramesRead;       // total number of frames read successfully
+    uint32_t mReadErrors;       // total number of read() errors
+    uint32_t mSampleRate;
+    size_t   mFrameCount;
+};
+
+}   // android
+
+#endif  // ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
diff --git a/services/audioflinger/FastCaptureState.cpp b/services/audioflinger/FastCaptureState.cpp
index 1d029b7..c4d5e45 100644
--- a/services/audioflinger/FastCaptureState.cpp
+++ b/services/audioflinger/FastCaptureState.cpp
@@ -27,4 +27,19 @@
 {
 }
 
+// static
+const char *FastCaptureState::commandToString(Command command)
+{
+    const char *str = FastThreadState::commandToString(command);
+    if (str != NULL) {
+        return str;
+    }
+    switch (command) {
+    case FastCaptureState::READ:        return "READ";
+    case FastCaptureState::WRITE:       return "WRITE";
+    case FastCaptureState::READ_WRITE:  return "READ_WRITE";
+    }
+    LOG_ALWAYS_FATAL("%s", __func__);
+}
+
 }   // android
diff --git a/services/audioflinger/FastCaptureState.h b/services/audioflinger/FastCaptureState.h
index 29c865a..9bca2d4 100644
--- a/services/audioflinger/FastCaptureState.h
+++ b/services/audioflinger/FastCaptureState.h
@@ -29,21 +29,23 @@
     /*virtual*/ ~FastCaptureState();
 
     // all pointer fields use raw pointers; objects are owned and ref-counted by RecordThread
-    NBAIO_Source    *mInputSource;      // HAL input device, must already be negotiated
+    NBAIO_Source*   mInputSource;       // HAL input device, must already be negotiated
     // FIXME by renaming, could pull up these fields to FastThreadState
     int             mInputSourceGen;    // increment when mInputSource is assigned
-    NBAIO_Sink      *mPipeSink;         // after reading from input source, write to this pipe sink
+    NBAIO_Sink*     mPipeSink;          // after reading from input source, write to this pipe sink
     int             mPipeSinkGen;       // increment when mPipeSink is assigned
     size_t          mFrameCount;        // number of frames per fast capture buffer
-    audio_track_cblk_t  *mCblk;         // control block for the single fast client, or NULL
+    audio_track_cblk_t* mCblk;          // control block for the single fast client, or NULL
 
     // Extends FastThreadState::Command
     static const Command
         // The following commands also process configuration changes, and can be "or"ed:
-        READ = 0x8,             // read from input source
-        WRITE = 0x10,           // write to pipe sink
-        READ_WRITE = 0x18;      // read from input source and write to pipe sink
+        READ = 0x8,                     // read from input source
+        WRITE = 0x10,                   // write to pipe sink
+        READ_WRITE = 0x18;              // read from input source and write to pipe sink
 
+    // never returns NULL; asserts if command is invalid
+    static const char *commandToString(Command command);
 };  // struct FastCaptureState
 
 }   // namespace android
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 2678cbf..f1cf0aa 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -27,10 +27,11 @@
 
 #include "Configuration.h"
 #include <time.h>
+#include <utils/Debug.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
 #include <system/audio.h>
-#ifdef FAST_MIXER_STATISTICS
+#ifdef FAST_THREAD_STATISTICS
 #include <cpustats/CentralTendencyStatistics.h>
 #ifdef CPU_FREQUENCY_STATISTICS
 #include <cpustats/ThreadCpuUsage.h>
@@ -44,15 +45,15 @@
 
 namespace android {
 
-/*static*/ const FastMixerState FastMixer::initial;
+/*static*/ const FastMixerState FastMixer::sInitial;
 
 FastMixer::FastMixer() : FastThread(),
-    slopNs(0),
-    // fastTrackNames
-    // generations
-    outputSink(NULL),
-    outputSinkGen(0),
-    mixer(NULL),
+    mSlopNs(0),
+    // mFastTrackNames
+    // mGenerations
+    mOutputSink(NULL),
+    mOutputSinkGen(0),
+    mMixer(NULL),
     mSinkBuffer(NULL),
     mSinkBufferSize(0),
     mSinkChannelCount(FCC_2),
@@ -60,30 +61,30 @@
     mMixerBufferSize(0),
     mMixerBufferFormat(AUDIO_FORMAT_PCM_16_BIT),
     mMixerBufferState(UNDEFINED),
-    format(Format_Invalid),
-    sampleRate(0),
-    fastTracksGen(0),
-    totalNativeFramesWritten(0),
+    mFormat(Format_Invalid),
+    mSampleRate(0),
+    mFastTracksGen(0),
+    mTotalNativeFramesWritten(0),
     // timestamp
-    nativeFramesWrittenButNotPresented(0)   // the = 0 is to silence the compiler
+    mNativeFramesWrittenButNotPresented(0)   // the = 0 is to silence the compiler
 {
-    // FIXME pass initial as parameter to base class constructor, and make it static local
-    previous = &initial;
-    current = &initial;
+    // FIXME pass sInitial as parameter to base class constructor, and make it static local
+    mPrevious = &sInitial;
+    mCurrent = &sInitial;
 
-    mDummyDumpState = &dummyDumpState;
+    mDummyDumpState = &mDummyFastMixerDumpState;
     // TODO: Add channel mask to NBAIO_Format.
     // We assume that the channel mask must be a valid positional channel mask.
     mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
 
     unsigned i;
     for (i = 0; i < FastMixerState::kMaxFastTracks; ++i) {
-        fastTrackNames[i] = -1;
-        generations[i] = 0;
+        mFastTrackNames[i] = -1;
+        mGenerations[i] = 0;
     }
-#ifdef FAST_MIXER_STATISTICS
-    oldLoad.tv_sec = 0;
-    oldLoad.tv_nsec = 0;
+#ifdef FAST_THREAD_STATISTICS
+    mOldLoad.tv_sec = 0;
+    mOldLoad.tv_nsec = 0;
 #endif
 }
 
@@ -103,20 +104,20 @@
 
 void FastMixer::setLog(NBLog::Writer *logWriter)
 {
-    if (mixer != NULL) {
-        mixer->setLog(logWriter);
+    if (mMixer != NULL) {
+        mMixer->setLog(logWriter);
     }
 }
 
 void FastMixer::onIdle()
 {
-    preIdle = *(const FastMixerState *)current;
-    current = &preIdle;
+    mPreIdle = *(const FastMixerState *)mCurrent;
+    mCurrent = &mPreIdle;
 }
 
 void FastMixer::onExit()
 {
-    delete mixer;
+    delete mMixer;
     free(mMixerBuffer);
     free(mSinkBuffer);
 }
@@ -135,82 +136,84 @@
 
 void FastMixer::onStateChange()
 {
-    const FastMixerState * const current = (const FastMixerState *) this->current;
-    const FastMixerState * const previous = (const FastMixerState *) this->previous;
-    FastMixerDumpState * const dumpState = (FastMixerDumpState *) this->dumpState;
+    const FastMixerState * const current = (const FastMixerState *) mCurrent;
+    const FastMixerState * const previous = (const FastMixerState *) mPrevious;
+    FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState;
     const size_t frameCount = current->mFrameCount;
 
     // handle state change here, but since we want to diff the state,
-    // we're prepared for previous == &initial the first time through
+    // we're prepared for previous == &sInitial the first time through
     unsigned previousTrackMask;
 
     // check for change in output HAL configuration
-    NBAIO_Format previousFormat = format;
-    if (current->mOutputSinkGen != outputSinkGen) {
-        outputSink = current->mOutputSink;
-        outputSinkGen = current->mOutputSinkGen;
-        if (outputSink == NULL) {
-            format = Format_Invalid;
-            sampleRate = 0;
+    NBAIO_Format previousFormat = mFormat;
+    if (current->mOutputSinkGen != mOutputSinkGen) {
+        mOutputSink = current->mOutputSink;
+        mOutputSinkGen = current->mOutputSinkGen;
+        if (mOutputSink == NULL) {
+            mFormat = Format_Invalid;
+            mSampleRate = 0;
             mSinkChannelCount = 0;
             mSinkChannelMask = AUDIO_CHANNEL_NONE;
         } else {
-            format = outputSink->format();
-            sampleRate = Format_sampleRate(format);
-            mSinkChannelCount = Format_channelCount(format);
+            mFormat = mOutputSink->format();
+            mSampleRate = Format_sampleRate(mFormat);
+            mSinkChannelCount = Format_channelCount(mFormat);
             LOG_ALWAYS_FATAL_IF(mSinkChannelCount > AudioMixer::MAX_NUM_CHANNELS);
 
             // TODO: Add channel mask to NBAIO_Format
             // We assume that the channel mask must be a valid positional channel mask.
             mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
         }
-        dumpState->mSampleRate = sampleRate;
+        dumpState->mSampleRate = mSampleRate;
     }
 
-    if ((!Format_isEqual(format, previousFormat)) || (frameCount != previous->mFrameCount)) {
+    if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
         // FIXME to avoid priority inversion, don't delete here
-        delete mixer;
-        mixer = NULL;
+        delete mMixer;
+        mMixer = NULL;
         free(mMixerBuffer);
         mMixerBuffer = NULL;
         free(mSinkBuffer);
         mSinkBuffer = NULL;
-        if (frameCount > 0 && sampleRate > 0) {
+        if (frameCount > 0 && mSampleRate > 0) {
             // FIXME new may block for unbounded time at internal mutex of the heap
             //       implementation; it would be better to have normal mixer allocate for us
             //       to avoid blocking here and to prevent possible priority inversion
-            mixer = new AudioMixer(frameCount, sampleRate, FastMixerState::kMaxFastTracks);
+            mMixer = new AudioMixer(frameCount, mSampleRate, FastMixerState::kMaxFastTracks);
             const size_t mixerFrameSize = mSinkChannelCount
                     * audio_bytes_per_sample(mMixerBufferFormat);
             mMixerBufferSize = mixerFrameSize * frameCount;
             (void)posix_memalign(&mMixerBuffer, 32, mMixerBufferSize);
             const size_t sinkFrameSize = mSinkChannelCount
-                    * audio_bytes_per_sample(format.mFormat);
+                    * audio_bytes_per_sample(mFormat.mFormat);
             if (sinkFrameSize > mixerFrameSize) { // need a sink buffer
                 mSinkBufferSize = sinkFrameSize * frameCount;
                 (void)posix_memalign(&mSinkBuffer, 32, mSinkBufferSize);
             }
-            periodNs = (frameCount * 1000000000LL) / sampleRate;    // 1.00
-            underrunNs = (frameCount * 1750000000LL) / sampleRate;  // 1.75
-            overrunNs = (frameCount * 500000000LL) / sampleRate;    // 0.50
-            forceNs = (frameCount * 950000000LL) / sampleRate;      // 0.95
-            warmupNs = (frameCount * 500000000LL) / sampleRate;     // 0.50
+            mPeriodNs = (frameCount * 1000000000LL) / mSampleRate;    // 1.00
+            mUnderrunNs = (frameCount * 1750000000LL) / mSampleRate;  // 1.75
+            mOverrunNs = (frameCount * 500000000LL) / mSampleRate;    // 0.50
+            mForceNs = (frameCount * 950000000LL) / mSampleRate;      // 0.95
+            mWarmupNsMin = (frameCount * 750000000LL) / mSampleRate;  // 0.75
+            mWarmupNsMax = (frameCount * 1250000000LL) / mSampleRate; // 1.25
         } else {
-            periodNs = 0;
-            underrunNs = 0;
-            overrunNs = 0;
-            forceNs = 0;
-            warmupNs = 0;
+            mPeriodNs = 0;
+            mUnderrunNs = 0;
+            mOverrunNs = 0;
+            mForceNs = 0;
+            mWarmupNsMin = 0;
+            mWarmupNsMax = LONG_MAX;
         }
         mMixerBufferState = UNDEFINED;
 #if !LOG_NDEBUG
         for (unsigned i = 0; i < FastMixerState::kMaxFastTracks; ++i) {
-            fastTrackNames[i] = -1;
+            mFastTrackNames[i] = -1;
         }
 #endif
         // we need to reconfigure all active tracks
         previousTrackMask = 0;
-        fastTracksGen = current->mFastTracksGen - 1;
+        mFastTracksGen = current->mFastTracksGen - 1;
         dumpState->mFrameCount = frameCount;
     } else {
         previousTrackMask = previous->mTrackMask;
@@ -219,7 +222,7 @@
     // check for change in active track set
     const unsigned currentTrackMask = current->mTrackMask;
     dumpState->mTrackMask = currentTrackMask;
-    if (current->mFastTracksGen != fastTracksGen) {
+    if (current->mFastTracksGen != mFastTracksGen) {
         ALOG_ASSERT(mMixerBuffer != NULL);
         int name;
 
@@ -230,16 +233,16 @@
             removedTracks &= ~(1 << i);
             const FastTrack* fastTrack = &current->mFastTracks[i];
             ALOG_ASSERT(fastTrack->mBufferProvider == NULL);
-            if (mixer != NULL) {
-                name = fastTrackNames[i];
+            if (mMixer != NULL) {
+                name = mFastTrackNames[i];
                 ALOG_ASSERT(name >= 0);
-                mixer->deleteTrackName(name);
+                mMixer->deleteTrackName(name);
             }
 #if !LOG_NDEBUG
-            fastTrackNames[i] = -1;
+            mFastTrackNames[i] = -1;
 #endif
             // don't reset track dump state, since other side is ignoring it
-            generations[i] = fastTrack->mGeneration;
+            mGenerations[i] = fastTrack->mGeneration;
         }
 
         // now process added tracks
@@ -249,29 +252,29 @@
             addedTracks &= ~(1 << i);
             const FastTrack* fastTrack = &current->mFastTracks[i];
             AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider;
-            ALOG_ASSERT(bufferProvider != NULL && fastTrackNames[i] == -1);
-            if (mixer != NULL) {
-                name = mixer->getTrackName(fastTrack->mChannelMask,
+            ALOG_ASSERT(bufferProvider != NULL && mFastTrackNames[i] == -1);
+            if (mMixer != NULL) {
+                name = mMixer->getTrackName(fastTrack->mChannelMask,
                         fastTrack->mFormat, AUDIO_SESSION_OUTPUT_MIX);
                 ALOG_ASSERT(name >= 0);
-                fastTrackNames[i] = name;
-                mixer->setBufferProvider(name, bufferProvider);
-                mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
+                mFastTrackNames[i] = name;
+                mMixer->setBufferProvider(name, bufferProvider);
+                mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
                         (void *)mMixerBuffer);
                 // newly allocated track names default to full scale volume
-                mixer->setParameter(
+                mMixer->setParameter(
                         name,
                         AudioMixer::TRACK,
                         AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
-                mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT,
+                mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT,
                         (void *)(uintptr_t)fastTrack->mFormat);
-                mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
+                mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
                         (void *)(uintptr_t)fastTrack->mChannelMask);
-                mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
+                mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
                         (void *)(uintptr_t)mSinkChannelMask);
-                mixer->enable(name);
+                mMixer->enable(name);
             }
-            generations[i] = fastTrack->mGeneration;
+            mGenerations[i] = fastTrack->mGeneration;
         }
 
         // finally process (potentially) modified tracks; these use the same slot
@@ -281,38 +284,38 @@
             int i = __builtin_ctz(modifiedTracks);
             modifiedTracks &= ~(1 << i);
             const FastTrack* fastTrack = &current->mFastTracks[i];
-            if (fastTrack->mGeneration != generations[i]) {
+            if (fastTrack->mGeneration != mGenerations[i]) {
                 // this track was actually modified
                 AudioBufferProvider *bufferProvider = fastTrack->mBufferProvider;
                 ALOG_ASSERT(bufferProvider != NULL);
-                if (mixer != NULL) {
-                    name = fastTrackNames[i];
+                if (mMixer != NULL) {
+                    name = mFastTrackNames[i];
                     ALOG_ASSERT(name >= 0);
-                    mixer->setBufferProvider(name, bufferProvider);
+                    mMixer->setBufferProvider(name, bufferProvider);
                     if (fastTrack->mVolumeProvider == NULL) {
                         float f = AudioMixer::UNITY_GAIN_FLOAT;
-                        mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f);
-                        mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f);
+                        mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f);
+                        mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f);
                     }
-                    mixer->setParameter(name, AudioMixer::RESAMPLE,
+                    mMixer->setParameter(name, AudioMixer::RESAMPLE,
                             AudioMixer::REMOVE, NULL);
-                    mixer->setParameter(
+                    mMixer->setParameter(
                             name,
                             AudioMixer::TRACK,
                             AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
-                    mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT,
+                    mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::FORMAT,
                             (void *)(uintptr_t)fastTrack->mFormat);
-                    mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
+                    mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK,
                             (void *)(uintptr_t)fastTrack->mChannelMask);
-                    mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
+                    mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
                             (void *)(uintptr_t)mSinkChannelMask);
                     // already enabled
                 }
-                generations[i] = fastTrack->mGeneration;
+                mGenerations[i] = fastTrack->mGeneration;
             }
         }
 
-        fastTracksGen = current->mFastTracksGen;
+        mFastTracksGen = current->mFastTracksGen;
 
         dumpState->mNumTracks = popcount(currentTrackMask);
     }
@@ -320,12 +323,12 @@
 
 void FastMixer::onWork()
 {
-    const FastMixerState * const current = (const FastMixerState *) this->current;
-    FastMixerDumpState * const dumpState = (FastMixerDumpState *) this->dumpState;
-    const FastMixerState::Command command = this->command;
+    const FastMixerState * const current = (const FastMixerState *) mCurrent;
+    FastMixerDumpState * const dumpState = (FastMixerDumpState *) mDumpState;
+    const FastMixerState::Command command = mCommand;
     const size_t frameCount = current->mFrameCount;
 
-    if ((command & FastMixerState::MIX) && (mixer != NULL) && isWarm) {
+    if ((command & FastMixerState::MIX) && (mMixer != NULL) && mIsWarm) {
         ALOG_ASSERT(mMixerBuffer != NULL);
         // for each track, update volume and check for underrun
         unsigned currentTrackMask = current->mTrackMask;
@@ -335,9 +338,9 @@
             const FastTrack* fastTrack = &current->mFastTracks[i];
 
             // Refresh the per-track timestamp
-            if (timestampStatus == NO_ERROR) {
+            if (mTimestampStatus == NO_ERROR) {
                 uint32_t trackFramesWrittenButNotPresented =
-                    nativeFramesWrittenButNotPresented;
+                    mNativeFramesWrittenButNotPresented;
                 uint32_t trackFramesWritten = fastTrack->mBufferProvider->framesReleased();
                 // Can't provide an AudioTimestamp before first frame presented,
                 // or during the brief 32-bit wraparound window
@@ -345,20 +348,20 @@
                     AudioTimestamp perTrackTimestamp;
                     perTrackTimestamp.mPosition =
                             trackFramesWritten - trackFramesWrittenButNotPresented;
-                    perTrackTimestamp.mTime = timestamp.mTime;
+                    perTrackTimestamp.mTime = mTimestamp.mTime;
                     fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
                 }
             }
 
-            int name = fastTrackNames[i];
+            int name = mFastTrackNames[i];
             ALOG_ASSERT(name >= 0);
             if (fastTrack->mVolumeProvider != NULL) {
                 gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
                 float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
                 float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
 
-                mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &vlf);
-                mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &vrf);
+                mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &vlf);
+                mMixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &vrf);
             }
             // FIXME The current implementation of framesReady() for fast tracks
             // takes a tryLock, which can block
@@ -379,43 +382,44 @@
                 if (framesReady == 0) {
                     underruns.mBitFields.mEmpty++;
                     underruns.mBitFields.mMostRecent = UNDERRUN_EMPTY;
-                    mixer->disable(name);
+                    mMixer->disable(name);
                 } else {
                     // allow mixing partial buffer
                     underruns.mBitFields.mPartial++;
                     underruns.mBitFields.mMostRecent = UNDERRUN_PARTIAL;
-                    mixer->enable(name);
+                    mMixer->enable(name);
                 }
             } else {
                 underruns.mBitFields.mFull++;
                 underruns.mBitFields.mMostRecent = UNDERRUN_FULL;
-                mixer->enable(name);
+                mMixer->enable(name);
             }
             ftDump->mUnderruns = underruns;
             ftDump->mFramesReady = framesReady;
         }
 
         int64_t pts;
-        if (outputSink == NULL || (OK != outputSink->getNextWriteTimestamp(&pts))) {
+        if (mOutputSink == NULL || (OK != mOutputSink->getNextWriteTimestamp(&pts))) {
             pts = AudioBufferProvider::kInvalidPTS;
         }
 
         // process() is CPU-bound
-        mixer->process(pts);
+        mMixer->process(pts);
         mMixerBufferState = MIXED;
     } else if (mMixerBufferState == MIXED) {
         mMixerBufferState = UNDEFINED;
     }
     //bool didFullWrite = false;    // dumpsys could display a count of partial writes
-    if ((command & FastMixerState::WRITE) && (outputSink != NULL) && (mMixerBuffer != NULL)) {
+    if ((command & FastMixerState::WRITE) && (mOutputSink != NULL) && (mMixerBuffer != NULL)) {
         if (mMixerBufferState == UNDEFINED) {
             memset(mMixerBuffer, 0, mMixerBufferSize);
             mMixerBufferState = ZEROED;
         }
+        // prepare the buffer used to write to sink
         void *buffer = mSinkBuffer != NULL ? mSinkBuffer : mMixerBuffer;
-        if (format.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format
-            memcpy_by_audio_format(buffer, format.mFormat, mMixerBuffer, mMixerBufferFormat,
-                    frameCount * Format_channelCount(format));
+        if (mFormat.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format
+            memcpy_by_audio_format(buffer, mFormat.mFormat, mMixerBuffer, mMixerBufferFormat,
+                    frameCount * Format_channelCount(mFormat));
         }
         // if non-NULL, then duplicate write() to this non-blocking sink
         NBAIO_Sink* teeSink;
@@ -426,252 +430,34 @@
         //       but this code should be modified to handle both non-blocking and blocking sinks
         dumpState->mWriteSequence++;
         ATRACE_BEGIN("write");
-        ssize_t framesWritten = outputSink->write(buffer, frameCount);
+        ssize_t framesWritten = mOutputSink->write(buffer, frameCount);
         ATRACE_END();
         dumpState->mWriteSequence++;
         if (framesWritten >= 0) {
             ALOG_ASSERT((size_t) framesWritten <= frameCount);
-            totalNativeFramesWritten += framesWritten;
-            dumpState->mFramesWritten = totalNativeFramesWritten;
+            mTotalNativeFramesWritten += framesWritten;
+            dumpState->mFramesWritten = mTotalNativeFramesWritten;
             //if ((size_t) framesWritten == frameCount) {
             //    didFullWrite = true;
             //}
         } else {
             dumpState->mWriteErrors++;
         }
-        attemptedWrite = true;
+        mAttemptedWrite = true;
         // FIXME count # of writes blocked excessively, CPU usage, etc. for dump
 
-        timestampStatus = outputSink->getTimestamp(timestamp);
-        if (timestampStatus == NO_ERROR) {
-            uint32_t totalNativeFramesPresented = timestamp.mPosition;
-            if (totalNativeFramesPresented <= totalNativeFramesWritten) {
-                nativeFramesWrittenButNotPresented =
-                    totalNativeFramesWritten - totalNativeFramesPresented;
+        mTimestampStatus = mOutputSink->getTimestamp(mTimestamp);
+        if (mTimestampStatus == NO_ERROR) {
+            uint32_t totalNativeFramesPresented = mTimestamp.mPosition;
+            if (totalNativeFramesPresented <= mTotalNativeFramesWritten) {
+                mNativeFramesWrittenButNotPresented =
+                    mTotalNativeFramesWritten - totalNativeFramesPresented;
             } else {
                 // HAL reported that more frames were presented than were written
-                timestampStatus = INVALID_OPERATION;
+                mTimestampStatus = INVALID_OPERATION;
             }
         }
     }
 }
 
-FastMixerDumpState::FastMixerDumpState(
-#ifdef FAST_MIXER_STATISTICS
-        uint32_t samplingN
-#endif
-        ) : FastThreadDumpState(),
-    mWriteSequence(0), mFramesWritten(0),
-    mNumTracks(0), mWriteErrors(0),
-    mSampleRate(0), mFrameCount(0),
-    mTrackMask(0)
-{
-#ifdef FAST_MIXER_STATISTICS
-    increaseSamplingN(samplingN);
-#endif
-}
-
-#ifdef FAST_MIXER_STATISTICS
-void FastMixerDumpState::increaseSamplingN(uint32_t samplingN)
-{
-    if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) {
-        return;
-    }
-    uint32_t additional = samplingN - mSamplingN;
-    // sample arrays aren't accessed atomically with respect to the bounds,
-    // so clearing reduces chance for dumpsys to read random uninitialized samples
-    memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional);
-    memset(&mLoadNs[mSamplingN], 0, sizeof(mLoadNs[0]) * additional);
-#ifdef CPU_FREQUENCY_STATISTICS
-    memset(&mCpukHz[mSamplingN], 0, sizeof(mCpukHz[0]) * additional);
-#endif
-    mSamplingN = samplingN;
-}
-#endif
-
-FastMixerDumpState::~FastMixerDumpState()
-{
-}
-
-// helper function called by qsort()
-static int compare_uint32_t(const void *pa, const void *pb)
-{
-    uint32_t a = *(const uint32_t *)pa;
-    uint32_t b = *(const uint32_t *)pb;
-    if (a < b) {
-        return -1;
-    } else if (a > b) {
-        return 1;
-    } else {
-        return 0;
-    }
-}
-
-void FastMixerDumpState::dump(int fd) const
-{
-    if (mCommand == FastMixerState::INITIAL) {
-        dprintf(fd, "  FastMixer not initialized\n");
-        return;
-    }
-#define COMMAND_MAX 32
-    char string[COMMAND_MAX];
-    switch (mCommand) {
-    case FastMixerState::INITIAL:
-        strcpy(string, "INITIAL");
-        break;
-    case FastMixerState::HOT_IDLE:
-        strcpy(string, "HOT_IDLE");
-        break;
-    case FastMixerState::COLD_IDLE:
-        strcpy(string, "COLD_IDLE");
-        break;
-    case FastMixerState::EXIT:
-        strcpy(string, "EXIT");
-        break;
-    case FastMixerState::MIX:
-        strcpy(string, "MIX");
-        break;
-    case FastMixerState::WRITE:
-        strcpy(string, "WRITE");
-        break;
-    case FastMixerState::MIX_WRITE:
-        strcpy(string, "MIX_WRITE");
-        break;
-    default:
-        snprintf(string, COMMAND_MAX, "%d", mCommand);
-        break;
-    }
-    double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
-            (mMeasuredWarmupTs.tv_nsec / 1000000.0);
-    double mixPeriodSec = (double) mFrameCount / (double) mSampleRate;
-    dprintf(fd, "  FastMixer command=%s writeSequence=%u framesWritten=%u\n"
-                "            numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
-                "            sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
-                "            mixPeriod=%.2f ms\n",
-                 string, mWriteSequence, mFramesWritten,
-                 mNumTracks, mWriteErrors, mUnderruns, mOverruns,
-                 mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles,
-                 mixPeriodSec * 1e3);
-#ifdef FAST_MIXER_STATISTICS
-    // find the interval of valid samples
-    uint32_t bounds = mBounds;
-    uint32_t newestOpen = bounds & 0xFFFF;
-    uint32_t oldestClosed = bounds >> 16;
-    uint32_t n = (newestOpen - oldestClosed) & 0xFFFF;
-    if (n > mSamplingN) {
-        ALOGE("too many samples %u", n);
-        n = mSamplingN;
-    }
-    // statistics for monotonic (wall clock) time, thread raw CPU load in time, CPU clock frequency,
-    // and adjusted CPU load in MHz normalized for CPU clock frequency
-    CentralTendencyStatistics wall, loadNs;
-#ifdef CPU_FREQUENCY_STATISTICS
-    CentralTendencyStatistics kHz, loadMHz;
-    uint32_t previousCpukHz = 0;
-#endif
-    // Assuming a normal distribution for cycle times, three standard deviations on either side of
-    // the mean account for 99.73% of the population.  So if we take each tail to be 1/1000 of the
-    // sample set, we get 99.8% combined, or close to three standard deviations.
-    static const uint32_t kTailDenominator = 1000;
-    uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL;
-    // loop over all the samples
-    for (uint32_t j = 0; j < n; ++j) {
-        size_t i = oldestClosed++ & (mSamplingN - 1);
-        uint32_t wallNs = mMonotonicNs[i];
-        if (tail != NULL) {
-            tail[j] = wallNs;
-        }
-        wall.sample(wallNs);
-        uint32_t sampleLoadNs = mLoadNs[i];
-        loadNs.sample(sampleLoadNs);
-#ifdef CPU_FREQUENCY_STATISTICS
-        uint32_t sampleCpukHz = mCpukHz[i];
-        // skip bad kHz samples
-        if ((sampleCpukHz & ~0xF) != 0) {
-            kHz.sample(sampleCpukHz >> 4);
-            if (sampleCpukHz == previousCpukHz) {
-                double megacycles = (double) sampleLoadNs * (double) (sampleCpukHz >> 4) * 1e-12;
-                double adjMHz = megacycles / mixPeriodSec;  // _not_ wallNs * 1e9
-                loadMHz.sample(adjMHz);
-            }
-        }
-        previousCpukHz = sampleCpukHz;
-#endif
-    }
-    if (n) {
-        dprintf(fd, "  Simple moving statistics over last %.1f seconds:\n",
-                    wall.n() * mixPeriodSec);
-        dprintf(fd, "    wall clock time in ms per mix cycle:\n"
-                    "      mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
-                    wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6,
-                    wall.stddev()*1e-6);
-        dprintf(fd, "    raw CPU load in us per mix cycle:\n"
-                    "      mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
-                    loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3,
-                    loadNs.stddev()*1e-3);
-    } else {
-        dprintf(fd, "  No FastMixer statistics available currently\n");
-    }
-#ifdef CPU_FREQUENCY_STATISTICS
-    dprintf(fd, "  CPU clock frequency in MHz:\n"
-                "    mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
-                kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3);
-    dprintf(fd, "  adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n"
-                "    mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
-                loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev());
-#endif
-    if (tail != NULL) {
-        qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
-        // assume same number of tail samples on each side, left and right
-        uint32_t count = n / kTailDenominator;
-        CentralTendencyStatistics left, right;
-        for (uint32_t i = 0; i < count; ++i) {
-            left.sample(tail[i]);
-            right.sample(tail[n - (i + 1)]);
-        }
-        dprintf(fd, "  Distribution of mix cycle times in ms for the tails (> ~3 stddev outliers):\n"
-                    "    left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n"
-                    "    right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
-                    left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6,
-                    right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6,
-                    right.stddev()*1e-6);
-        delete[] tail;
-    }
-#endif
-    // The active track mask and track states are updated non-atomically.
-    // So if we relied on isActive to decide whether to display,
-    // then we might display an obsolete track or omit an active track.
-    // Instead we always display all tracks, with an indication
-    // of whether we think the track is active.
-    uint32_t trackMask = mTrackMask;
-    dprintf(fd, "  Fast tracks: kMaxFastTracks=%u activeMask=%#x\n",
-            FastMixerState::kMaxFastTracks, trackMask);
-    dprintf(fd, "  Index Active Full Partial Empty  Recent Ready\n");
-    for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) {
-        bool isActive = trackMask & 1;
-        const FastTrackDump *ftDump = &mTracks[i];
-        const FastTrackUnderruns& underruns = ftDump->mUnderruns;
-        const char *mostRecent;
-        switch (underruns.mBitFields.mMostRecent) {
-        case UNDERRUN_FULL:
-            mostRecent = "full";
-            break;
-        case UNDERRUN_PARTIAL:
-            mostRecent = "partial";
-            break;
-        case UNDERRUN_EMPTY:
-            mostRecent = "empty";
-            break;
-        default:
-            mostRecent = "?";
-            break;
-        }
-        dprintf(fd, "  %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no",
-                (underruns.mBitFields.mFull) & UNDERRUN_MASK,
-                (underruns.mBitFields.mPartial) & UNDERRUN_MASK,
-                (underruns.mBitFields.mEmpty) & UNDERRUN_MASK,
-                mostRecent, ftDump->mFramesReady);
-    }
-}
-
 }   // namespace android
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h
index fde8c2b..06a68fb 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/FastMixer.h
@@ -17,11 +17,7 @@
 #ifndef ANDROID_AUDIO_FAST_MIXER_H
 #define ANDROID_AUDIO_FAST_MIXER_H
 
-#include <linux/futex.h>
-#include <sys/syscall.h>
-#include <utils/Debug.h>
 #include "FastThread.h"
-#include <utils/Thread.h>
 #include "StateQueue.h"
 #include "FastMixerState.h"
 #include "FastMixerDumpState.h"
@@ -52,36 +48,39 @@
     virtual void onStateChange();
     virtual void onWork();
 
-    // FIXME these former local variables need comments and to be renamed to have "m" prefix
-    static const FastMixerState initial;
-    FastMixerState preIdle; // copy of state before we went into idle
-    long slopNs;        // accumulated time we've woken up too early (> 0) or too late (< 0)
-    int fastTrackNames[FastMixerState::kMaxFastTracks]; // handles used by mixer to identify tracks
-    int generations[FastMixerState::kMaxFastTracks];    // last observed mFastTracks[i].mGeneration
-    NBAIO_Sink *outputSink;
-    int outputSinkGen;
-    AudioMixer* mixer;
+    // FIXME these former local variables need comments
+    static const FastMixerState sInitial;
+
+    FastMixerState  mPreIdle;   // copy of state before we went into idle
+    long            mSlopNs;    // accumulated time we've woken up too early (> 0) or too late (< 0)
+    int             mFastTrackNames[FastMixerState::kMaxFastTracks];
+                                // handles used by mixer to identify tracks
+    int             mGenerations[FastMixerState::kMaxFastTracks];
+                                // last observed mFastTracks[i].mGeneration
+    NBAIO_Sink*     mOutputSink;
+    int             mOutputSinkGen;
+    AudioMixer*     mMixer;
 
     // mSinkBuffer audio format is stored in format.mFormat.
-    void* mSinkBuffer;                  // used for mixer output format translation
+    void*           mSinkBuffer;        // used for mixer output format translation
                                         // if sink format is different than mixer output.
-    size_t mSinkBufferSize;
-    uint32_t mSinkChannelCount;
+    size_t          mSinkBufferSize;
+    uint32_t        mSinkChannelCount;
     audio_channel_mask_t mSinkChannelMask;
-    void* mMixerBuffer;                 // mixer output buffer.
-    size_t mMixerBufferSize;
-    audio_format_t mMixerBufferFormat;  // mixer output format: AUDIO_FORMAT_PCM_(16_BIT|FLOAT).
+    void*           mMixerBuffer;       // mixer output buffer.
+    size_t          mMixerBufferSize;
+    audio_format_t  mMixerBufferFormat; // mixer output format: AUDIO_FORMAT_PCM_(16_BIT|FLOAT).
 
     enum {UNDEFINED, MIXED, ZEROED} mMixerBufferState;
-    NBAIO_Format format;
-    unsigned sampleRate;
-    int fastTracksGen;
-    FastMixerDumpState dummyDumpState;
-    uint32_t totalNativeFramesWritten;  // copied to dumpState->mFramesWritten
+    NBAIO_Format    mFormat;
+    unsigned        mSampleRate;
+    int             mFastTracksGen;
+    FastMixerDumpState mDummyFastMixerDumpState;
+    uint32_t        mTotalNativeFramesWritten;  // copied to dumpState->mFramesWritten
 
     // next 2 fields are valid only when timestampStatus == NO_ERROR
-    AudioTimestamp timestamp;
-    uint32_t nativeFramesWrittenButNotPresented;
+    AudioTimestamp  mTimestamp;
+    uint32_t        mNativeFramesWrittenButNotPresented;
 
 };  // class FastMixer
 
diff --git a/services/audioflinger/FastMixerDumpState.cpp b/services/audioflinger/FastMixerDumpState.cpp
new file mode 100644
index 0000000..b10942b
--- /dev/null
+++ b/services/audioflinger/FastMixerDumpState.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2014 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 "FastMixerDumpState"
+//#define LOG_NDEBUG 0
+
+#include "Configuration.h"
+#ifdef FAST_THREAD_STATISTICS
+#include <cpustats/CentralTendencyStatistics.h>
+#ifdef CPU_FREQUENCY_STATISTICS
+#include <cpustats/ThreadCpuUsage.h>
+#endif
+#endif
+#include <utils/Debug.h>
+#include <utils/Log.h>
+#include "FastMixerDumpState.h"
+
+namespace android {
+
+FastMixerDumpState::FastMixerDumpState() : FastThreadDumpState(),
+    mWriteSequence(0), mFramesWritten(0),
+    mNumTracks(0), mWriteErrors(0),
+    mSampleRate(0), mFrameCount(0),
+    mTrackMask(0)
+{
+}
+
+FastMixerDumpState::~FastMixerDumpState()
+{
+}
+
+// helper function called by qsort()
+static int compare_uint32_t(const void *pa, const void *pb)
+{
+    uint32_t a = *(const uint32_t *)pa;
+    uint32_t b = *(const uint32_t *)pb;
+    if (a < b) {
+        return -1;
+    } else if (a > b) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+void FastMixerDumpState::dump(int fd) const
+{
+    if (mCommand == FastMixerState::INITIAL) {
+        dprintf(fd, "  FastMixer not initialized\n");
+        return;
+    }
+    double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+            (mMeasuredWarmupTs.tv_nsec / 1000000.0);
+    double mixPeriodSec = (double) mFrameCount / mSampleRate;
+    dprintf(fd, "  FastMixer command=%s writeSequence=%u framesWritten=%u\n"
+                "            numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
+                "            sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
+                "            mixPeriod=%.2f ms\n",
+                FastMixerState::commandToString(mCommand), mWriteSequence, mFramesWritten,
+                mNumTracks, mWriteErrors, mUnderruns, mOverruns,
+                mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles,
+                mixPeriodSec * 1e3);
+#ifdef FAST_THREAD_STATISTICS
+    // find the interval of valid samples
+    uint32_t bounds = mBounds;
+    uint32_t newestOpen = bounds & 0xFFFF;
+    uint32_t oldestClosed = bounds >> 16;
+    uint32_t n = (newestOpen - oldestClosed) & 0xFFFF;
+    if (n > mSamplingN) {
+        ALOGE("too many samples %u", n);
+        n = mSamplingN;
+    }
+    // statistics for monotonic (wall clock) time, thread raw CPU load in time, CPU clock frequency,
+    // and adjusted CPU load in MHz normalized for CPU clock frequency
+    CentralTendencyStatistics wall, loadNs;
+#ifdef CPU_FREQUENCY_STATISTICS
+    CentralTendencyStatistics kHz, loadMHz;
+    uint32_t previousCpukHz = 0;
+#endif
+    // Assuming a normal distribution for cycle times, three standard deviations on either side of
+    // the mean account for 99.73% of the population.  So if we take each tail to be 1/1000 of the
+    // sample set, we get 99.8% combined, or close to three standard deviations.
+    static const uint32_t kTailDenominator = 1000;
+    uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL;
+    // loop over all the samples
+    for (uint32_t j = 0; j < n; ++j) {
+        size_t i = oldestClosed++ & (mSamplingN - 1);
+        uint32_t wallNs = mMonotonicNs[i];
+        if (tail != NULL) {
+            tail[j] = wallNs;
+        }
+        wall.sample(wallNs);
+        uint32_t sampleLoadNs = mLoadNs[i];
+        loadNs.sample(sampleLoadNs);
+#ifdef CPU_FREQUENCY_STATISTICS
+        uint32_t sampleCpukHz = mCpukHz[i];
+        // skip bad kHz samples
+        if ((sampleCpukHz & ~0xF) != 0) {
+            kHz.sample(sampleCpukHz >> 4);
+            if (sampleCpukHz == previousCpukHz) {
+                double megacycles = (double) sampleLoadNs * (double) (sampleCpukHz >> 4) * 1e-12;
+                double adjMHz = megacycles / mixPeriodSec;  // _not_ wallNs * 1e9
+                loadMHz.sample(adjMHz);
+            }
+        }
+        previousCpukHz = sampleCpukHz;
+#endif
+    }
+    if (n) {
+        dprintf(fd, "  Simple moving statistics over last %.1f seconds:\n",
+                    wall.n() * mixPeriodSec);
+        dprintf(fd, "    wall clock time in ms per mix cycle:\n"
+                    "      mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
+                    wall.mean()*1e-6, wall.minimum()*1e-6, wall.maximum()*1e-6,
+                    wall.stddev()*1e-6);
+        dprintf(fd, "    raw CPU load in us per mix cycle:\n"
+                    "      mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
+                    loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3,
+                    loadNs.stddev()*1e-3);
+    } else {
+        dprintf(fd, "  No FastMixer statistics available currently\n");
+    }
+#ifdef CPU_FREQUENCY_STATISTICS
+    dprintf(fd, "  CPU clock frequency in MHz:\n"
+                "    mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
+                kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3);
+    dprintf(fd, "  adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n"
+                "    mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
+                loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev());
+#endif
+    if (tail != NULL) {
+        qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
+        // assume same number of tail samples on each side, left and right
+        uint32_t count = n / kTailDenominator;
+        CentralTendencyStatistics left, right;
+        for (uint32_t i = 0; i < count; ++i) {
+            left.sample(tail[i]);
+            right.sample(tail[n - (i + 1)]);
+        }
+        dprintf(fd, "  Distribution of mix cycle times in ms for the tails "
+                    "(> ~3 stddev outliers):\n"
+                    "    left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n"
+                    "    right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
+                    left.mean()*1e-6, left.minimum()*1e-6, left.maximum()*1e-6, left.stddev()*1e-6,
+                    right.mean()*1e-6, right.minimum()*1e-6, right.maximum()*1e-6,
+                    right.stddev()*1e-6);
+        delete[] tail;
+    }
+#endif
+    // The active track mask and track states are updated non-atomically.
+    // So if we relied on isActive to decide whether to display,
+    // then we might display an obsolete track or omit an active track.
+    // Instead we always display all tracks, with an indication
+    // of whether we think the track is active.
+    uint32_t trackMask = mTrackMask;
+    dprintf(fd, "  Fast tracks: kMaxFastTracks=%u activeMask=%#x\n",
+            FastMixerState::kMaxFastTracks, trackMask);
+    dprintf(fd, "  Index Active Full Partial Empty  Recent Ready\n");
+    for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) {
+        bool isActive = trackMask & 1;
+        const FastTrackDump *ftDump = &mTracks[i];
+        const FastTrackUnderruns& underruns = ftDump->mUnderruns;
+        const char *mostRecent;
+        switch (underruns.mBitFields.mMostRecent) {
+        case UNDERRUN_FULL:
+            mostRecent = "full";
+            break;
+        case UNDERRUN_PARTIAL:
+            mostRecent = "partial";
+            break;
+        case UNDERRUN_EMPTY:
+            mostRecent = "empty";
+            break;
+        default:
+            mostRecent = "?";
+            break;
+        }
+        dprintf(fd, "  %5u %6s %4u %7u %5u %7s %5zu\n", i, isActive ? "yes" : "no",
+                (underruns.mBitFields.mFull) & UNDERRUN_MASK,
+                (underruns.mBitFields.mPartial) & UNDERRUN_MASK,
+                (underruns.mBitFields.mEmpty) & UNDERRUN_MASK,
+                mostRecent, ftDump->mFramesReady);
+    }
+}
+
+}   // android
diff --git a/services/audioflinger/FastMixerDumpState.h b/services/audioflinger/FastMixerDumpState.h
index 6a1e4649..ac15e7c 100644
--- a/services/audioflinger/FastMixerDumpState.h
+++ b/services/audioflinger/FastMixerDumpState.h
@@ -17,7 +17,10 @@
 #ifndef ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
 #define ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
 
+#include <stdint.h>
 #include "Configuration.h"
+#include "FastThreadDumpState.h"
+#include "FastMixerState.h"
 
 namespace android {
 
@@ -52,22 +55,12 @@
 struct FastTrackDump {
     FastTrackDump() : mFramesReady(0) { }
     /*virtual*/ ~FastTrackDump() { }
-    FastTrackUnderruns mUnderruns;
-    size_t mFramesReady;        // most recent value only; no long-term statistics kept
+    FastTrackUnderruns  mUnderruns;
+    size_t              mFramesReady;        // most recent value only; no long-term statistics kept
 };
 
-// The FastMixerDumpState keeps a cache of FastMixer statistics that can be logged by dumpsys.
-// Each individual native word-sized field is accessed atomically.  But the
-// overall structure is non-atomic, that is there may be an inconsistency between fields.
-// No barriers or locks are used for either writing or reading.
-// Only POD types are permitted, and the contents shouldn't be trusted (i.e. do range checks).
-// It has a different lifetime than the FastMixer, and so it can't be a member of FastMixer.
 struct FastMixerDumpState : FastThreadDumpState {
-    FastMixerDumpState(
-#ifdef FAST_MIXER_STATISTICS
-            uint32_t samplingN = kSamplingNforLowRamDevice
-#endif
-            );
+    FastMixerDumpState();
     /*virtual*/ ~FastMixerDumpState();
 
     void dump(int fd) const;    // should only be called on a stable copy, not the original
@@ -80,14 +73,6 @@
     size_t   mFrameCount;
     uint32_t mTrackMask;        // mask of active tracks
     FastTrackDump   mTracks[FastMixerState::kMaxFastTracks];
-
-#ifdef FAST_MIXER_STATISTICS
-    // Compile-time constant for a "low RAM device", must be a power of 2 <= kSamplingN.
-    // This value was chosen such that each array uses 1 small page (4 Kbytes).
-    static const uint32_t kSamplingNforLowRamDevice = 0x400;
-    // Increase sampling window after construction, must be a power of 2 <= kSamplingN
-    void    increaseSamplingN(uint32_t samplingN);
-#endif
 };
 
 }   // android
diff --git a/services/audioflinger/FastMixerState.cpp b/services/audioflinger/FastMixerState.cpp
index 3aa8dad..a8c2634 100644
--- a/services/audioflinger/FastMixerState.cpp
+++ b/services/audioflinger/FastMixerState.cpp
@@ -39,4 +39,19 @@
 {
 }
 
+// static
+const char *FastMixerState::commandToString(Command command)
+{
+    const char *str = FastThreadState::commandToString(command);
+    if (str != NULL) {
+        return str;
+    }
+    switch (command) {
+    case FastMixerState::MIX:       return "MIX";
+    case FastMixerState::WRITE:     return "WRITE";
+    case FastMixerState::MIX_WRITE: return "MIX_WRITE";
+    }
+    LOG_ALWAYS_FATAL("%s", __func__);
+}
+
 }   // namespace android
diff --git a/services/audioflinger/FastMixerState.h b/services/audioflinger/FastMixerState.h
index 661c9ca..916514f 100644
--- a/services/audioflinger/FastMixerState.h
+++ b/services/audioflinger/FastMixerState.h
@@ -73,6 +73,9 @@
 
     // This might be a one-time configuration rather than per-state
     NBAIO_Sink* mTeeSink;       // if non-NULL, then duplicate write()s to this non-blocking sink
+
+    // never returns NULL; asserts if command is invalid
+    static const char *commandToString(Command command);
 };  // struct FastMixerState
 
 }   // namespace android
diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/FastThread.cpp
index 216dace..5ca579b 100644
--- a/services/audioflinger/FastThread.cpp
+++ b/services/audioflinger/FastThread.cpp
@@ -25,54 +25,58 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 #include "FastThread.h"
+#include "FastThreadDumpState.h"
 
 #define FAST_DEFAULT_NS    999999999L   // ~1 sec: default time to sleep
 #define FAST_HOT_IDLE_NS     1000000L   // 1 ms: time to sleep while hot idling
-#define MIN_WARMUP_CYCLES          2    // minimum number of loop cycles to wait for warmup
+#define MIN_WARMUP_CYCLES          2    // minimum number of consecutive in-range loop cycles
+                                        // to wait for warmup
 #define MAX_WARMUP_CYCLES         10    // maximum number of loop cycles to wait for warmup
 
 namespace android {
 
 FastThread::FastThread() : Thread(false /*canCallJava*/),
-    // re-initialized to &initial by subclass constructor
-     previous(NULL), current(NULL),
-    /* oldTs({0, 0}), */
-    oldTsValid(false),
-    sleepNs(-1),
-    periodNs(0),
-    underrunNs(0),
-    overrunNs(0),
-    forceNs(0),
-    warmupNs(0),
-    // re-initialized to &dummyDumpState by subclass constructor
+    // re-initialized to &sInitial by subclass constructor
+    mPrevious(NULL), mCurrent(NULL),
+    /* mOldTs({0, 0}), */
+    mOldTsValid(false),
+    mSleepNs(-1),
+    mPeriodNs(0),
+    mUnderrunNs(0),
+    mOverrunNs(0),
+    mForceNs(0),
+    mWarmupNsMin(0),
+    mWarmupNsMax(LONG_MAX),
+    // re-initialized to &mDummySubclassDumpState by subclass constructor
     mDummyDumpState(NULL),
-    dumpState(NULL),
-    ignoreNextOverrun(true),
-#ifdef FAST_MIXER_STATISTICS
-    // oldLoad
-    oldLoadValid(false),
-    bounds(0),
-    full(false),
-    // tcu
+    mDumpState(NULL),
+    mIgnoreNextOverrun(true),
+#ifdef FAST_THREAD_STATISTICS
+    // mOldLoad
+    mOldLoadValid(false),
+    mBounds(0),
+    mFull(false),
+    // mTcu
 #endif
-    coldGen(0),
-    isWarm(false),
-    /* measuredWarmupTs({0, 0}), */
-    warmupCycles(0),
-    // dummyLogWriter
-    logWriter(&dummyLogWriter),
-    timestampStatus(INVALID_OPERATION),
+    mColdGen(0),
+    mIsWarm(false),
+    /* mMeasuredWarmupTs({0, 0}), */
+    mWarmupCycles(0),
+    mWarmupConsecutiveInRangeCycles(0),
+    // mDummyLogWriter
+    mLogWriter(&mDummyLogWriter),
+    mTimestampStatus(INVALID_OPERATION),
 
-    command(FastThreadState::INITIAL),
+    mCommand(FastThreadState::INITIAL),
 #if 0
     frameCount(0),
 #endif
-    attemptedWrite(false)
+    mAttemptedWrite(false)
 {
-    oldTs.tv_sec = 0;
-    oldTs.tv_nsec = 0;
-    measuredWarmupTs.tv_sec = 0;
-    measuredWarmupTs.tv_nsec = 0;
+    mOldTs.tv_sec = 0;
+    mOldTs.tv_nsec = 0;
+    mMeasuredWarmupTs.tv_sec = 0;
+    mMeasuredWarmupTs.tv_nsec = 0;
 }
 
 FastThread::~FastThread()
@@ -84,34 +88,34 @@
     for (;;) {
 
         // either nanosleep, sched_yield, or busy wait
-        if (sleepNs >= 0) {
-            if (sleepNs > 0) {
-                ALOG_ASSERT(sleepNs < 1000000000);
-                const struct timespec req = {0, sleepNs};
+        if (mSleepNs >= 0) {
+            if (mSleepNs > 0) {
+                ALOG_ASSERT(mSleepNs < 1000000000);
+                const struct timespec req = {0, mSleepNs};
                 nanosleep(&req, NULL);
             } else {
                 sched_yield();
             }
         }
         // default to long sleep for next cycle
-        sleepNs = FAST_DEFAULT_NS;
+        mSleepNs = FAST_DEFAULT_NS;
 
         // poll for state change
         const FastThreadState *next = poll();
         if (next == NULL) {
             // continue to use the default initial state until a real state is available
-            // FIXME &initial not available, should save address earlier
-            //ALOG_ASSERT(current == &initial && previous == &initial);
-            next = current;
+            // FIXME &sInitial not available, should save address earlier
+            //ALOG_ASSERT(mCurrent == &sInitial && previous == &sInitial);
+            next = mCurrent;
         }
 
-        command = next->mCommand;
-        if (next != current) {
+        mCommand = next->mCommand;
+        if (next != mCurrent) {
 
             // As soon as possible of learning of a new dump area, start using it
-            dumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
-            logWriter = next->mNBLogWriter != NULL ? next->mNBLogWriter : &dummyLogWriter;
-            setLog(logWriter);
+            mDumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
+            mLogWriter = next->mNBLogWriter != NULL ? next->mNBLogWriter : &mDummyLogWriter;
+            setLog(mLogWriter);
 
             // We want to always have a valid reference to the previous (non-idle) state.
             // However, the state queue only guarantees access to current and previous states.
@@ -122,37 +126,38 @@
             //  non-idle -> idle        update previous from copy of current
             //  idle     -> idle        don't update previous
             //  idle     -> non-idle    don't update previous
-            if (!(current->mCommand & FastThreadState::IDLE)) {
-                if (command & FastThreadState::IDLE) {
+            if (!(mCurrent->mCommand & FastThreadState::IDLE)) {
+                if (mCommand & FastThreadState::IDLE) {
                     onIdle();
-                    oldTsValid = false;
-#ifdef FAST_MIXER_STATISTICS
-                    oldLoadValid = false;
+                    mOldTsValid = false;
+#ifdef FAST_THREAD_STATISTICS
+                    mOldLoadValid = false;
 #endif
-                    ignoreNextOverrun = true;
+                    mIgnoreNextOverrun = true;
                 }
-                previous = current;
+                mPrevious = mCurrent;
             }
-            current = next;
+            mCurrent = next;
         }
 #if !LOG_NDEBUG
         next = NULL;    // not referenced again
 #endif
 
-        dumpState->mCommand = command;
+        mDumpState->mCommand = mCommand;
 
+        // FIXME what does this comment mean?
         // << current, previous, command, dumpState >>
 
-        switch (command) {
+        switch (mCommand) {
         case FastThreadState::INITIAL:
         case FastThreadState::HOT_IDLE:
-            sleepNs = FAST_HOT_IDLE_NS;
+            mSleepNs = FAST_HOT_IDLE_NS;
             continue;
         case FastThreadState::COLD_IDLE:
             // only perform a cold idle command once
             // FIXME consider checking previous state and only perform if previous != COLD_IDLE
-            if (current->mColdGen != coldGen) {
-                int32_t *coldFutexAddr = current->mColdFutexAddr;
+            if (mCurrent->mColdGen != mColdGen) {
+                int32_t *coldFutexAddr = mCurrent->mColdFutexAddr;
                 ALOG_ASSERT(coldFutexAddr != NULL);
                 int32_t old = android_atomic_dec(coldFutexAddr);
                 if (old <= 0) {
@@ -164,41 +169,42 @@
                 }
                 // This may be overly conservative; there could be times that the normal mixer
                 // requests such a brief cold idle that it doesn't require resetting this flag.
-                isWarm = false;
-                measuredWarmupTs.tv_sec = 0;
-                measuredWarmupTs.tv_nsec = 0;
-                warmupCycles = 0;
-                sleepNs = -1;
-                coldGen = current->mColdGen;
-#ifdef FAST_MIXER_STATISTICS
-                bounds = 0;
-                full = false;
+                mIsWarm = false;
+                mMeasuredWarmupTs.tv_sec = 0;
+                mMeasuredWarmupTs.tv_nsec = 0;
+                mWarmupCycles = 0;
+                mWarmupConsecutiveInRangeCycles = 0;
+                mSleepNs = -1;
+                mColdGen = mCurrent->mColdGen;
+#ifdef FAST_THREAD_STATISTICS
+                mBounds = 0;
+                mFull = false;
 #endif
-                oldTsValid = !clock_gettime(CLOCK_MONOTONIC, &oldTs);
-                timestampStatus = INVALID_OPERATION;
+                mOldTsValid = !clock_gettime(CLOCK_MONOTONIC, &mOldTs);
+                mTimestampStatus = INVALID_OPERATION;
             } else {
-                sleepNs = FAST_HOT_IDLE_NS;
+                mSleepNs = FAST_HOT_IDLE_NS;
             }
             continue;
         case FastThreadState::EXIT:
             onExit();
             return false;
         default:
-            LOG_ALWAYS_FATAL_IF(!isSubClassCommand(command));
+            LOG_ALWAYS_FATAL_IF(!isSubClassCommand(mCommand));
             break;
         }
 
         // there is a non-idle state available to us; did the state change?
-        if (current != previous) {
+        if (mCurrent != mPrevious) {
             onStateChange();
 #if 1   // FIXME shouldn't need this
             // only process state change once
-            previous = current;
+            mPrevious = mCurrent;
 #endif
         }
 
         // do work using current state here
-        attemptedWrite = false;
+        mAttemptedWrite = false;
         onWork();
 
         // To be exactly periodic, compute the next sleep time based on current time.
@@ -207,13 +213,13 @@
         struct timespec newTs;
         int rc = clock_gettime(CLOCK_MONOTONIC, &newTs);
         if (rc == 0) {
-            //logWriter->logTimestamp(newTs);
-            if (oldTsValid) {
-                time_t sec = newTs.tv_sec - oldTs.tv_sec;
-                long nsec = newTs.tv_nsec - oldTs.tv_nsec;
+            //mLogWriter->logTimestamp(newTs);
+            if (mOldTsValid) {
+                time_t sec = newTs.tv_sec - mOldTs.tv_sec;
+                long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
                 ALOGE_IF(sec < 0 || (sec == 0 && nsec < 0),
                         "clock_gettime(CLOCK_MONOTONIC) failed: was %ld.%09ld but now %ld.%09ld",
-                        oldTs.tv_sec, oldTs.tv_nsec, newTs.tv_sec, newTs.tv_nsec);
+                        mOldTs.tv_sec, mOldTs.tv_nsec, newTs.tv_sec, newTs.tv_nsec);
                 if (nsec < 0) {
                     --sec;
                     nsec += 1000000000;
@@ -221,62 +227,70 @@
                 // To avoid an initial underrun on fast tracks after exiting standby,
                 // do not start pulling data from tracks and mixing until warmup is complete.
                 // Warmup is considered complete after the earlier of:
-                //      MIN_WARMUP_CYCLES write() attempts and last one blocks for at least warmupNs
+                //      MIN_WARMUP_CYCLES consecutive in-range write() attempts,
+                //          where "in-range" means mWarmupNsMin <= cycle time <= mWarmupNsMax
                 //      MAX_WARMUP_CYCLES write() attempts.
                 // This is overly conservative, but to get better accuracy requires a new HAL API.
-                if (!isWarm && attemptedWrite) {
-                    measuredWarmupTs.tv_sec += sec;
-                    measuredWarmupTs.tv_nsec += nsec;
-                    if (measuredWarmupTs.tv_nsec >= 1000000000) {
-                        measuredWarmupTs.tv_sec++;
-                        measuredWarmupTs.tv_nsec -= 1000000000;
+                if (!mIsWarm && mAttemptedWrite) {
+                    mMeasuredWarmupTs.tv_sec += sec;
+                    mMeasuredWarmupTs.tv_nsec += nsec;
+                    if (mMeasuredWarmupTs.tv_nsec >= 1000000000) {
+                        mMeasuredWarmupTs.tv_sec++;
+                        mMeasuredWarmupTs.tv_nsec -= 1000000000;
                     }
-                    ++warmupCycles;
-                    if ((nsec > warmupNs && warmupCycles >= MIN_WARMUP_CYCLES) ||
-                            (warmupCycles >= MAX_WARMUP_CYCLES)) {
-                        isWarm = true;
-                        dumpState->mMeasuredWarmupTs = measuredWarmupTs;
-                        dumpState->mWarmupCycles = warmupCycles;
+                    ++mWarmupCycles;
+                    if (mWarmupNsMin <= nsec && nsec <= mWarmupNsMax) {
+                        ALOGV("warmup cycle %d in range: %.03f ms", mWarmupCycles, nsec * 1e-9);
+                        ++mWarmupConsecutiveInRangeCycles;
+                    } else {
+                        ALOGV("warmup cycle %d out of range: %.03f ms", mWarmupCycles, nsec * 1e-9);
+                        mWarmupConsecutiveInRangeCycles = 0;
+                    }
+                    if ((mWarmupConsecutiveInRangeCycles >= MIN_WARMUP_CYCLES) ||
+                            (mWarmupCycles >= MAX_WARMUP_CYCLES)) {
+                        mIsWarm = true;
+                        mDumpState->mMeasuredWarmupTs = mMeasuredWarmupTs;
+                        mDumpState->mWarmupCycles = mWarmupCycles;
                     }
                 }
-                sleepNs = -1;
-                if (isWarm) {
-                    if (sec > 0 || nsec > underrunNs) {
+                mSleepNs = -1;
+                if (mIsWarm) {
+                    if (sec > 0 || nsec > mUnderrunNs) {
                         ATRACE_NAME("underrun");
                         // FIXME only log occasionally
                         ALOGV("underrun: time since last cycle %d.%03ld sec",
                                 (int) sec, nsec / 1000000L);
-                        dumpState->mUnderruns++;
-                        ignoreNextOverrun = true;
-                    } else if (nsec < overrunNs) {
-                        if (ignoreNextOverrun) {
-                            ignoreNextOverrun = false;
+                        mDumpState->mUnderruns++;
+                        mIgnoreNextOverrun = true;
+                    } else if (nsec < mOverrunNs) {
+                        if (mIgnoreNextOverrun) {
+                            mIgnoreNextOverrun = false;
                         } else {
                             // FIXME only log occasionally
                             ALOGV("overrun: time since last cycle %d.%03ld sec",
                                     (int) sec, nsec / 1000000L);
-                            dumpState->mOverruns++;
+                            mDumpState->mOverruns++;
                         }
                         // This forces a minimum cycle time. It:
                         //  - compensates for an audio HAL with jitter due to sample rate conversion
                         //  - works with a variable buffer depth audio HAL that never pulls at a
-                        //    rate < than overrunNs per buffer.
+                        //    rate < than mOverrunNs per buffer.
                         //  - recovers from overrun immediately after underrun
                         // It doesn't work with a non-blocking audio HAL.
-                        sleepNs = forceNs - nsec;
+                        mSleepNs = mForceNs - nsec;
                     } else {
-                        ignoreNextOverrun = false;
+                        mIgnoreNextOverrun = false;
                     }
                 }
-#ifdef FAST_MIXER_STATISTICS
-                if (isWarm) {
+#ifdef FAST_THREAD_STATISTICS
+                if (mIsWarm) {
                     // advance the FIFO queue bounds
-                    size_t i = bounds & (dumpState->mSamplingN - 1);
-                    bounds = (bounds & 0xFFFF0000) | ((bounds + 1) & 0xFFFF);
-                    if (full) {
-                        bounds += 0x10000;
-                    } else if (!(bounds & (dumpState->mSamplingN - 1))) {
-                        full = true;
+                    size_t i = mBounds & (mDumpState->mSamplingN - 1);
+                    mBounds = (mBounds & 0xFFFF0000) | ((mBounds + 1) & 0xFFFF);
+                    if (mFull) {
+                        mBounds += 0x10000;
+                    } else if (!(mBounds & (mDumpState->mSamplingN - 1))) {
+                        mFull = true;
                     }
                     // compute the delta value of clock_gettime(CLOCK_MONOTONIC)
                     uint32_t monotonicNs = nsec;
@@ -288,9 +302,9 @@
                     struct timespec newLoad;
                     rc = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &newLoad);
                     if (rc == 0) {
-                        if (oldLoadValid) {
-                            sec = newLoad.tv_sec - oldLoad.tv_sec;
-                            nsec = newLoad.tv_nsec - oldLoad.tv_nsec;
+                        if (mOldLoadValid) {
+                            sec = newLoad.tv_sec - mOldLoad.tv_sec;
+                            nsec = newLoad.tv_nsec - mOldLoad.tv_nsec;
                             if (nsec < 0) {
                                 --sec;
                                 nsec += 1000000000;
@@ -301,42 +315,42 @@
                             }
                         } else {
                             // first time through the loop
-                            oldLoadValid = true;
+                            mOldLoadValid = true;
                         }
-                        oldLoad = newLoad;
+                        mOldLoad = newLoad;
                     }
 #ifdef CPU_FREQUENCY_STATISTICS
                     // get the absolute value of CPU clock frequency in kHz
                     int cpuNum = sched_getcpu();
-                    uint32_t kHz = tcu.getCpukHz(cpuNum);
+                    uint32_t kHz = mTcu.getCpukHz(cpuNum);
                     kHz = (kHz << 4) | (cpuNum & 0xF);
 #endif
                     // save values in FIFO queues for dumpsys
                     // these stores #1, #2, #3 are not atomic with respect to each other,
                     // or with respect to store #4 below
-                    dumpState->mMonotonicNs[i] = monotonicNs;
-                    dumpState->mLoadNs[i] = loadNs;
+                    mDumpState->mMonotonicNs[i] = monotonicNs;
+                    mDumpState->mLoadNs[i] = loadNs;
 #ifdef CPU_FREQUENCY_STATISTICS
-                    dumpState->mCpukHz[i] = kHz;
+                    mDumpState->mCpukHz[i] = kHz;
 #endif
                     // this store #4 is not atomic with respect to stores #1, #2, #3 above, but
                     // the newest open & oldest closed halves are atomic with respect to each other
-                    dumpState->mBounds = bounds;
+                    mDumpState->mBounds = mBounds;
                     ATRACE_INT("cycle_ms", monotonicNs / 1000000);
                     ATRACE_INT("load_us", loadNs / 1000);
                 }
 #endif
             } else {
                 // first time through the loop
-                oldTsValid = true;
-                sleepNs = periodNs;
-                ignoreNextOverrun = true;
+                mOldTsValid = true;
+                mSleepNs = mPeriodNs;
+                mIgnoreNextOverrun = true;
             }
-            oldTs = newTs;
+            mOldTs = newTs;
         } else {
             // monotonic clock is broken
-            oldTsValid = false;
-            sleepNs = periodNs;
+            mOldTsValid = false;
+            mSleepNs = mPeriodNs;
         }
 
     }   // for (;;)
diff --git a/services/audioflinger/FastThread.h b/services/audioflinger/FastThread.h
index 1330334..2efb6de 100644
--- a/services/audioflinger/FastThread.h
+++ b/services/audioflinger/FastThread.h
@@ -48,42 +48,45 @@
     virtual void onStateChange() = 0;
     virtual void onWork() = 0;
 
-    // FIXME these former local variables need comments and to be renamed to have an "m" prefix
-    const FastThreadState *previous;
-    const FastThreadState *current;
-    struct timespec oldTs;
-    bool oldTsValid;
-    long sleepNs;   // -1: busy wait, 0: sched_yield, > 0: nanosleep
-    long periodNs;      // expected period; the time required to render one mix buffer
-    long underrunNs;    // underrun likely when write cycle is greater than this value
-    long overrunNs;     // overrun likely when write cycle is less than this value
-    long forceNs;       // if overrun detected, force the write cycle to take this much time
-    long warmupNs;      // warmup complete when write cycle is greater than to this value
-    FastThreadDumpState *mDummyDumpState;
-    FastThreadDumpState *dumpState;
-    bool ignoreNextOverrun;  // used to ignore initial overrun and first after an underrun
-#ifdef FAST_MIXER_STATISTICS
-    struct timespec oldLoad;    // previous value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
-    bool oldLoadValid;  // whether oldLoad is valid
-    uint32_t bounds;
-    bool full;          // whether we have collected at least mSamplingN samples
+    // FIXME these former local variables need comments
+    const FastThreadState*  mPrevious;
+    const FastThreadState*  mCurrent;
+    struct timespec mOldTs;
+    bool            mOldTsValid;
+    long            mSleepNs;       // -1: busy wait, 0: sched_yield, > 0: nanosleep
+    long            mPeriodNs;      // expected period; the time required to render one mix buffer
+    long            mUnderrunNs;    // underrun likely when write cycle is greater than this value
+    long            mOverrunNs;     // overrun likely when write cycle is less than this value
+    long            mForceNs;       // if overrun detected,
+                                    // force the write cycle to take this much time
+    long            mWarmupNsMin;   // warmup complete when write cycle is greater than or equal to
+                                    // this value
+    long            mWarmupNsMax;   // and less than or equal to this value
+    FastThreadDumpState* mDummyDumpState;
+    FastThreadDumpState* mDumpState;
+    bool            mIgnoreNextOverrun;     // used to ignore initial overrun and first after an
+                                            // underrun
+#ifdef FAST_THREAD_STATISTICS
+    struct timespec mOldLoad;       // previous value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
+    bool            mOldLoadValid;  // whether oldLoad is valid
+    uint32_t        mBounds;
+    bool            mFull;          // whether we have collected at least mSamplingN samples
 #ifdef CPU_FREQUENCY_STATISTICS
-    ThreadCpuUsage tcu;     // for reading the current CPU clock frequency in kHz
+    ThreadCpuUsage  mTcu;           // for reading the current CPU clock frequency in kHz
 #endif
 #endif
-    unsigned coldGen;   // last observed mColdGen
-    bool isWarm;        // true means ready to mix, false means wait for warmup before mixing
-    struct timespec measuredWarmupTs;  // how long did it take for warmup to complete
-    uint32_t warmupCycles;  // counter of number of loop cycles required to warmup
-    NBLog::Writer dummyLogWriter;
-    NBLog::Writer *logWriter;
-    status_t timestampStatus;
+    unsigned        mColdGen;       // last observed mColdGen
+    bool            mIsWarm;        // true means ready to mix,
+                                    // false means wait for warmup before mixing
+    struct timespec mMeasuredWarmupTs;  // how long did it take for warmup to complete
+    uint32_t        mWarmupCycles;  // counter of number of loop cycles during warmup phase
+    uint32_t        mWarmupConsecutiveInRangeCycles;    // number of consecutive cycles in range
+    NBLog::Writer   mDummyLogWriter;
+    NBLog::Writer*  mLogWriter;
+    status_t        mTimestampStatus;
 
-    FastThreadState::Command command;
-#if 0
-    size_t frameCount;
-#endif
-    bool attemptedWrite;
+    FastThreadState::Command mCommand;
+    bool            mAttemptedWrite;
 
 };  // class FastThread
 
diff --git a/services/audioflinger/FastThreadDumpState.cpp b/services/audioflinger/FastThreadDumpState.cpp
new file mode 100644
index 0000000..9df5c4c
--- /dev/null
+++ b/services/audioflinger/FastThreadDumpState.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 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 "FastThreadDumpState.h"
+
+namespace android {
+
+FastThreadDumpState::FastThreadDumpState() :
+    mCommand(FastThreadState::INITIAL), mUnderruns(0), mOverruns(0),
+    /* mMeasuredWarmupTs({0, 0}), */
+    mWarmupCycles(0)
+#ifdef FAST_THREAD_STATISTICS
+    , mSamplingN(0), mBounds(0)
+#endif
+{
+    mMeasuredWarmupTs.tv_sec = 0;
+    mMeasuredWarmupTs.tv_nsec = 0;
+#ifdef FAST_THREAD_STATISTICS
+    increaseSamplingN(1);
+#endif
+}
+
+FastThreadDumpState::~FastThreadDumpState()
+{
+}
+
+#ifdef FAST_THREAD_STATISTICS
+void FastThreadDumpState::increaseSamplingN(uint32_t samplingN)
+{
+    if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) {
+        return;
+    }
+    uint32_t additional = samplingN - mSamplingN;
+    // sample arrays aren't accessed atomically with respect to the bounds,
+    // so clearing reduces chance for dumpsys to read random uninitialized samples
+    memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional);
+    memset(&mLoadNs[mSamplingN], 0, sizeof(mLoadNs[0]) * additional);
+#ifdef CPU_FREQUENCY_STATISTICS
+    memset(&mCpukHz[mSamplingN], 0, sizeof(mCpukHz[0]) * additional);
+#endif
+    mSamplingN = samplingN;
+}
+#endif
+
+}   // android
diff --git a/services/audioflinger/FastThreadDumpState.h b/services/audioflinger/FastThreadDumpState.h
new file mode 100644
index 0000000..1ce0914
--- /dev/null
+++ b/services/audioflinger/FastThreadDumpState.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2014 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_AUDIO_FAST_THREAD_DUMP_STATE_H
+#define ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
+
+#include "Configuration.h"
+#include "FastThreadState.h"
+
+namespace android {
+
+// The FastThreadDumpState keeps a cache of FastThread statistics that can be logged by dumpsys.
+// Each individual native word-sized field is accessed atomically.  But the
+// overall structure is non-atomic, that is there may be an inconsistency between fields.
+// No barriers or locks are used for either writing or reading.
+// Only POD types are permitted, and the contents shouldn't be trusted (i.e. do range checks).
+// It has a different lifetime than the FastThread, and so it can't be a member of FastThread.
+struct FastThreadDumpState {
+    FastThreadDumpState();
+    /*virtual*/ ~FastThreadDumpState();
+
+    FastThreadState::Command mCommand;   // current command
+    uint32_t mUnderruns;        // total number of underruns
+    uint32_t mOverruns;         // total number of overruns
+    struct timespec mMeasuredWarmupTs;  // measured warmup time
+    uint32_t mWarmupCycles;     // number of loop cycles required to warmup
+
+#ifdef FAST_THREAD_STATISTICS
+    // Recently collected samples of per-cycle monotonic time, thread CPU time, and CPU frequency.
+    // kSamplingN is max size of sampling frame (statistics), and must be a power of 2 <= 0x8000.
+    // The sample arrays are virtually allocated based on this compile-time constant,
+    // but are only initialized and used based on the runtime parameter mSamplingN.
+    static const uint32_t kSamplingN = 0x8000;
+    // Compile-time constant for a "low RAM device", must be a power of 2 <= kSamplingN.
+    // This value was chosen such that each array uses 1 small page (4 Kbytes).
+    static const uint32_t kSamplingNforLowRamDevice = 0x400;
+    // Corresponding runtime maximum size of sample arrays, must be a power of 2 <= kSamplingN.
+    uint32_t mSamplingN;
+    // The bounds define the interval of valid samples, and are represented as follows:
+    //      newest open (excluded) endpoint   = lower 16 bits of bounds, modulo N
+    //      oldest closed (included) endpoint = upper 16 bits of bounds, modulo N
+    // Number of valid samples is newest - oldest.
+    uint32_t mBounds;                   // bounds for mMonotonicNs, mThreadCpuNs, and mCpukHz
+    // The elements in the *Ns arrays are in units of nanoseconds <= 3999999999.
+    uint32_t mMonotonicNs[kSamplingN];  // delta monotonic (wall clock) time
+    uint32_t mLoadNs[kSamplingN];       // delta CPU load in time
+#ifdef CPU_FREQUENCY_STATISTICS
+    uint32_t mCpukHz[kSamplingN];       // absolute CPU clock frequency in kHz, bits 0-3 are CPU#
+#endif
+
+    // Increase sampling window after construction, must be a power of 2 <= kSamplingN
+    void    increaseSamplingN(uint32_t samplingN);
+#endif
+
+};  // struct FastThreadDumpState
+
+}   // android
+
+#endif  // ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
diff --git a/services/audioflinger/FastThreadState.cpp b/services/audioflinger/FastThreadState.cpp
index 6994872..ad5f31f 100644
--- a/services/audioflinger/FastThreadState.cpp
+++ b/services/audioflinger/FastThreadState.cpp
@@ -29,21 +29,16 @@
 {
 }
 
-
-FastThreadDumpState::FastThreadDumpState() :
-    mCommand(FastThreadState::INITIAL), mUnderruns(0), mOverruns(0),
-    /* mMeasuredWarmupTs({0, 0}), */
-    mWarmupCycles(0)
-#ifdef FAST_MIXER_STATISTICS
-    , mSamplingN(1), mBounds(0)
-#endif
+// static
+const char *FastThreadState::commandToString(FastThreadState::Command command)
 {
-    mMeasuredWarmupTs.tv_sec = 0;
-    mMeasuredWarmupTs.tv_nsec = 0;
-}
-
-FastThreadDumpState::~FastThreadDumpState()
-{
+    switch (command) {
+    case FastThreadState::INITIAL:      return "INITIAL";
+    case FastThreadState::HOT_IDLE:     return "HOT_IDLE";
+    case FastThreadState::COLD_IDLE:    return "COLD_IDLE";
+    case FastThreadState::EXIT:         return "EXIT";
+    }
+    return NULL;
 }
 
 }   // namespace android
diff --git a/services/audioflinger/FastThreadState.h b/services/audioflinger/FastThreadState.h
index 1ab8a0a..f18f846 100644
--- a/services/audioflinger/FastThreadState.h
+++ b/services/audioflinger/FastThreadState.h
@@ -46,43 +46,10 @@
     FastThreadDumpState* mDumpState; // if non-NULL, then update dump state periodically
     NBLog::Writer* mNBLogWriter; // non-blocking logger
 
+    // returns NULL if command belongs to a subclass
+    static const char *commandToString(Command command);
 };  // struct FastThreadState
 
-
-// FIXME extract common part of comment at FastMixerDumpState
-struct FastThreadDumpState {
-    FastThreadDumpState();
-    /*virtual*/ ~FastThreadDumpState();
-
-    FastThreadState::Command mCommand;   // current command
-    uint32_t mUnderruns;        // total number of underruns
-    uint32_t mOverruns;         // total number of overruns
-    struct timespec mMeasuredWarmupTs;  // measured warmup time
-    uint32_t mWarmupCycles;     // number of loop cycles required to warmup
-
-#ifdef FAST_MIXER_STATISTICS
-    // Recently collected samples of per-cycle monotonic time, thread CPU time, and CPU frequency.
-    // kSamplingN is max size of sampling frame (statistics), and must be a power of 2 <= 0x8000.
-    // The sample arrays are virtually allocated based on this compile-time constant,
-    // but are only initialized and used based on the runtime parameter mSamplingN.
-    static const uint32_t kSamplingN = 0x8000;
-    // Corresponding runtime maximum size of sample arrays, must be a power of 2 <= kSamplingN.
-    uint32_t mSamplingN;
-    // The bounds define the interval of valid samples, and are represented as follows:
-    //      newest open (excluded) endpoint   = lower 16 bits of bounds, modulo N
-    //      oldest closed (included) endpoint = upper 16 bits of bounds, modulo N
-    // Number of valid samples is newest - oldest.
-    uint32_t mBounds;                   // bounds for mMonotonicNs, mThreadCpuNs, and mCpukHz
-    // The elements in the *Ns arrays are in units of nanoseconds <= 3999999999.
-    uint32_t mMonotonicNs[kSamplingN];  // delta monotonic (wall clock) time
-    uint32_t mLoadNs[kSamplingN];       // delta CPU load in time
-#ifdef CPU_FREQUENCY_STATISTICS
-    uint32_t mCpukHz[kSamplingN];       // absolute CPU clock frequency in kHz, bits 0-3 are CPU#
-#endif
-#endif
-
-};  // struct FastThreadDumpState
-
 }   // android
 
 #endif  // ANDROID_AUDIO_FAST_THREAD_STATE_H
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 7544052..efbdcff 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -166,7 +166,9 @@
             if (*handle == mPatches[index]->mHandle) {
                 ALOGV("createAudioPatch() removing patch handle %d", *handle);
                 halHandle = mPatches[index]->mHalHandle;
+                Patch *removedPatch = mPatches[index];
                 mPatches.removeAt(index);
+                delete removedPatch;
                 break;
             }
         }
@@ -692,4 +694,4 @@
 }
 
 
-}; // namespace android
+} // namespace android
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index ee48276..902d5e4 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -255,7 +255,7 @@
 
     class Buffer : public AudioBufferProvider::Buffer {
     public:
-        int16_t *mBuffer;
+        void *mBuffer;
     };
 
                         OutputTrack(PlaybackThread *thread,
@@ -271,7 +271,7 @@
                                     AudioSystem::SYNC_EVENT_NONE,
                              int triggerSession = 0);
     virtual void        stop();
-            bool        write(int16_t* data, uint32_t frames);
+            bool        write(void* data, uint32_t frames);
             bool        bufferQueueEmpty() const { return mBufferQueue.size() == 0; }
             bool        isActive() const { return mActive; }
     const wp<ThreadBase>& thread() const { return mThread; }
diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/StateQueue.cpp
index 40d7bcd..9d4188f 100644
--- a/services/audioflinger/StateQueue.cpp
+++ b/services/audioflinger/StateQueue.cpp
@@ -48,7 +48,7 @@
     , mObserverDump(&mObserverDummyDump), mMutatorDump(&mMutatorDummyDump)
 #endif
 {
-    atomic_init(&mNext, 0);
+    atomic_init(&mNext, static_cast<uintptr_t>(0));
 }
 
 template<typename T> StateQueue<T>::~StateQueue()
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6b9da83..9881764 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -23,7 +23,9 @@
 #include "Configuration.h"
 #include <math.h>
 #include <fcntl.h>
+#include <linux/futex.h>
 #include <sys/stat.h>
+#include <sys/syscall.h>
 #include <cutils/properties.h>
 #include <media/AudioParameter.h>
 #include <media/AudioResamplerPublic.h>
@@ -314,6 +316,165 @@
 //      ThreadBase
 // ----------------------------------------------------------------------------
 
+// static
+const char *AudioFlinger::ThreadBase::threadTypeToString(AudioFlinger::ThreadBase::type_t type)
+{
+    switch (type) {
+    case MIXER:
+        return "MIXER";
+    case DIRECT:
+        return "DIRECT";
+    case DUPLICATING:
+        return "DUPLICATING";
+    case RECORD:
+        return "RECORD";
+    case OFFLOAD:
+        return "OFFLOAD";
+    default:
+        return "unknown";
+    }
+}
+
+String8 devicesToString(audio_devices_t devices)
+{
+    static const struct mapping {
+        audio_devices_t mDevices;
+        const char *    mString;
+    } mappingsOut[] = {
+        AUDIO_DEVICE_OUT_EARPIECE,          "EARPIECE",
+        AUDIO_DEVICE_OUT_SPEAKER,           "SPEAKER",
+        AUDIO_DEVICE_OUT_WIRED_HEADSET,     "WIRED_HEADSET",
+        AUDIO_DEVICE_OUT_WIRED_HEADPHONE,   "WIRED_HEADPHONE",
+        AUDIO_DEVICE_OUT_TELEPHONY_TX,      "TELEPHONY_TX",
+        AUDIO_DEVICE_NONE,                  "NONE",         // must be last
+    }, mappingsIn[] = {
+        AUDIO_DEVICE_IN_BUILTIN_MIC,        "BUILTIN_MIC",
+        AUDIO_DEVICE_IN_WIRED_HEADSET,      "WIRED_HEADSET",
+        AUDIO_DEVICE_IN_VOICE_CALL,         "VOICE_CALL",
+        AUDIO_DEVICE_IN_REMOTE_SUBMIX,      "REMOTE_SUBMIX",
+        AUDIO_DEVICE_NONE,                  "NONE",         // must be last
+    };
+    String8 result;
+    audio_devices_t allDevices = AUDIO_DEVICE_NONE;
+    const mapping *entry;
+    if (devices & AUDIO_DEVICE_BIT_IN) {
+        devices &= ~AUDIO_DEVICE_BIT_IN;
+        entry = mappingsIn;
+    } else {
+        entry = mappingsOut;
+    }
+    for ( ; entry->mDevices != AUDIO_DEVICE_NONE; entry++) {
+        allDevices = (audio_devices_t) (allDevices | entry->mDevices);
+        if (devices & entry->mDevices) {
+            if (!result.isEmpty()) {
+                result.append("|");
+            }
+            result.append(entry->mString);
+        }
+    }
+    if (devices & ~allDevices) {
+        if (!result.isEmpty()) {
+            result.append("|");
+        }
+        result.appendFormat("0x%X", devices & ~allDevices);
+    }
+    if (result.isEmpty()) {
+        result.append(entry->mString);
+    }
+    return result;
+}
+
+String8 inputFlagsToString(audio_input_flags_t flags)
+{
+    static const struct mapping {
+        audio_input_flags_t     mFlag;
+        const char *            mString;
+    } mappings[] = {
+        AUDIO_INPUT_FLAG_FAST,              "FAST",
+        AUDIO_INPUT_FLAG_HW_HOTWORD,        "HW_HOTWORD",
+        AUDIO_INPUT_FLAG_NONE,              "NONE",         // must be last
+    };
+    String8 result;
+    audio_input_flags_t allFlags = AUDIO_INPUT_FLAG_NONE;
+    const mapping *entry;
+    for (entry = mappings; entry->mFlag != AUDIO_INPUT_FLAG_NONE; entry++) {
+        allFlags = (audio_input_flags_t) (allFlags | entry->mFlag);
+        if (flags & entry->mFlag) {
+            if (!result.isEmpty()) {
+                result.append("|");
+            }
+            result.append(entry->mString);
+        }
+    }
+    if (flags & ~allFlags) {
+        if (!result.isEmpty()) {
+            result.append("|");
+        }
+        result.appendFormat("0x%X", flags & ~allFlags);
+    }
+    if (result.isEmpty()) {
+        result.append(entry->mString);
+    }
+    return result;
+}
+
+String8 outputFlagsToString(audio_output_flags_t flags)
+{
+    static const struct mapping {
+        audio_output_flags_t    mFlag;
+        const char *            mString;
+    } mappings[] = {
+        AUDIO_OUTPUT_FLAG_DIRECT,           "DIRECT",
+        AUDIO_OUTPUT_FLAG_PRIMARY,          "PRIMARY",
+        AUDIO_OUTPUT_FLAG_FAST,             "FAST",
+        AUDIO_OUTPUT_FLAG_DEEP_BUFFER,      "DEEP_BUFFER",
+        AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD, "COMPRESS_OFFLOAD",
+        AUDIO_OUTPUT_FLAG_NON_BLOCKING,     "NON_BLOCKING",
+        AUDIO_OUTPUT_FLAG_HW_AV_SYNC,       "HW_AV_SYNC",
+        AUDIO_OUTPUT_FLAG_NONE,             "NONE",         // must be last
+    };
+    String8 result;
+    audio_output_flags_t allFlags = AUDIO_OUTPUT_FLAG_NONE;
+    const mapping *entry;
+    for (entry = mappings; entry->mFlag != AUDIO_OUTPUT_FLAG_NONE; entry++) {
+        allFlags = (audio_output_flags_t) (allFlags | entry->mFlag);
+        if (flags & entry->mFlag) {
+            if (!result.isEmpty()) {
+                result.append("|");
+            }
+            result.append(entry->mString);
+        }
+    }
+    if (flags & ~allFlags) {
+        if (!result.isEmpty()) {
+            result.append("|");
+        }
+        result.appendFormat("0x%X", flags & ~allFlags);
+    }
+    if (result.isEmpty()) {
+        result.append(entry->mString);
+    }
+    return result;
+}
+
+const char *sourceToString(audio_source_t source)
+{
+    switch (source) {
+    case AUDIO_SOURCE_DEFAULT:              return "default";
+    case AUDIO_SOURCE_MIC:                  return "mic";
+    case AUDIO_SOURCE_VOICE_UPLINK:         return "voice uplink";
+    case AUDIO_SOURCE_VOICE_DOWNLINK:       return "voice downlink";
+    case AUDIO_SOURCE_VOICE_CALL:           return "voice call";
+    case AUDIO_SOURCE_CAMCORDER:            return "camcorder";
+    case AUDIO_SOURCE_VOICE_RECOGNITION:    return "voice recognition";
+    case AUDIO_SOURCE_VOICE_COMMUNICATION:  return "voice communication";
+    case AUDIO_SOURCE_REMOTE_SUBMIX:        return "remote submix";
+    case AUDIO_SOURCE_FM_TUNER:             return "FM tuner";
+    case AUDIO_SOURCE_HOTWORD:              return "hotword";
+    default:                                return "unknown";
+    }
+}
+
 AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
         audio_devices_t outDevice, audio_devices_t inDevice, type_t type)
     :   Thread(false /*canCallJava*/),
@@ -338,7 +499,7 @@
     // do not lock the mutex in destructor
     releaseWakeLock_l();
     if (mPowerManager != 0) {
-        sp<IBinder> binder = mPowerManager->asBinder();
+        sp<IBinder> binder = IInterface::asBinder(mPowerManager);
         binder->unlinkToDeath(mDeathRecipient);
     }
 }
@@ -577,20 +738,22 @@
 
     bool locked = AudioFlinger::dumpTryLock(mLock);
     if (!locked) {
-        dprintf(fd, "thread %p maybe dead locked\n", this);
+        dprintf(fd, "thread %p may be deadlocked\n", this);
     }
 
+    dprintf(fd, "  Thread name: %s\n", mThreadName);
     dprintf(fd, "  I/O handle: %d\n", mId);
     dprintf(fd, "  TID: %d\n", getTid());
     dprintf(fd, "  Standby: %s\n", mStandby ? "yes" : "no");
-    dprintf(fd, "  Sample rate: %u\n", mSampleRate);
+    dprintf(fd, "  Sample rate: %u Hz\n", mSampleRate);
     dprintf(fd, "  HAL frame count: %zu\n", mFrameCount);
+    dprintf(fd, "  HAL format: 0x%x (%s)\n", mHALFormat, formatToString(mHALFormat));
     dprintf(fd, "  HAL buffer size: %u bytes\n", mBufferSize);
-    dprintf(fd, "  Channel Count: %u\n", mChannelCount);
-    dprintf(fd, "  Channel Mask: 0x%08x (%s)\n", mChannelMask,
+    dprintf(fd, "  Channel count: %u\n", mChannelCount);
+    dprintf(fd, "  Channel mask: 0x%08x (%s)\n", mChannelMask,
             channelMaskToString(mChannelMask, mType != RECORD).string());
-    dprintf(fd, "  Format: 0x%x (%s)\n", mHALFormat, formatToString(mHALFormat));
-    dprintf(fd, "  Frame size: %zu\n", mFrameSize);
+    dprintf(fd, "  Format: 0x%x (%s)\n", mFormat, formatToString(mFormat));
+    dprintf(fd, "  Frame size: %zu bytes\n", mFrameSize);
     dprintf(fd, "  Pending config events:");
     size_t numConfig = mConfigEvents.size();
     if (numConfig) {
@@ -602,6 +765,9 @@
     } else {
         dprintf(fd, " none\n");
     }
+    dprintf(fd, "  Output device: %#x (%s)\n", mOutDevice, devicesToString(mOutDevice).string());
+    dprintf(fd, "  Input device: %#x (%s)\n", mInDevice, devicesToString(mInDevice).string());
+    dprintf(fd, "  Audio source: %d (%s)\n", mAudioSource, sourceToString(mAudioSource));
 
     if (locked) {
         mLock.unlock();
@@ -635,19 +801,19 @@
 String16 AudioFlinger::ThreadBase::getWakeLockTag()
 {
     switch (mType) {
-        case MIXER:
-            return String16("AudioMix");
-        case DIRECT:
-            return String16("AudioDirectOut");
-        case DUPLICATING:
-            return String16("AudioDup");
-        case RECORD:
-            return String16("AudioIn");
-        case OFFLOAD:
-            return String16("AudioOffload");
-        default:
-            ALOG_ASSERT(false);
-            return String16("AudioUnknown");
+    case MIXER:
+        return String16("AudioMix");
+    case DIRECT:
+        return String16("AudioDirectOut");
+    case DUPLICATING:
+        return String16("AudioDup");
+    case RECORD:
+        return String16("AudioIn");
+    case OFFLOAD:
+        return String16("AudioOffload");
+    default:
+        ALOG_ASSERT(false);
+        return String16("AudioUnknown");
     }
 }
 
@@ -674,7 +840,7 @@
         if (status == NO_ERROR) {
             mWakeLockToken = binder;
         }
-        ALOGV("acquireWakeLock_l() %s status %d", mName, status);
+        ALOGV("acquireWakeLock_l() %s status %d", mThreadName, status);
     }
 }
 
@@ -687,7 +853,7 @@
 void AudioFlinger::ThreadBase::releaseWakeLock_l()
 {
     if (mWakeLockToken != 0) {
-        ALOGV("releaseWakeLock_l() %s", mName);
+        ALOGV("releaseWakeLock_l() %s", mThreadName);
         if (mPowerManager != 0) {
             mPowerManager->releaseWakeLock(mWakeLockToken, 0,
                     true /* FIXME force oneway contrary to .aidl */);
@@ -708,7 +874,7 @@
         sp<IBinder> binder =
             defaultServiceManager()->checkService(String16("power"));
         if (binder == 0) {
-            ALOGW("Thread %s cannot connect to the power manager service", mName);
+            ALOGW("Thread %s cannot connect to the power manager service", mThreadName);
         } else {
             mPowerManager = interface_cast<IPowerManager>(binder);
             binder->linkToDeath(mDeathRecipient);
@@ -728,7 +894,7 @@
         status_t status;
         status = mPowerManager->updateWakeLockUids(mWakeLockToken, uids.size(), uids.array(),
                     true /* FIXME force oneway contrary to .aidl */);
-        ALOGV("acquireWakeLock_l() %s status %d", mName, status);
+        ALOGV("acquireWakeLock_l() %s status %d", mThreadName, status);
     }
 }
 
@@ -912,7 +1078,7 @@
     // mSinkBuffer is not guaranteed to be compatible with effect processing (PCM 16 stereo).
     if (mType == DIRECT) {
         ALOGW("createEffect_l() Cannot add effect %s on Direct output type thread %s",
-                desc->name, mName);
+                desc->name, mThreadName);
         lStatus = BAD_VALUE;
         goto Exit;
     }
@@ -936,7 +1102,8 @@
         case DUPLICATING:
         case RECORD:
         default:
-            ALOGW("createEffect_l() Cannot add global effect %s on thread %s", desc->name, mName);
+            ALOGW("createEffect_l() Cannot add global effect %s on thread %s",
+                    desc->name, mThreadName);
             lStatus = BAD_VALUE;
             goto Exit;
         }
@@ -1197,11 +1364,12 @@
         mScreenState(AudioFlinger::mScreenState),
         // index 0 is reserved for normal mixer's submix
         mFastTrackAvailMask(((1 << FastMixerState::kMaxFastTracks) - 1) & ~1),
+        mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
         // mLatchD, mLatchQ,
         mLatchDValid(false), mLatchQValid(false)
 {
-    snprintf(mName, kNameLength, "AudioOut_%X", id);
-    mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mName);
+    snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
+    mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
 
     // Assumes constructor is called by AudioFlinger with it's mLock held, but
     // it would be safer to explicitly pass initial masterVolume/masterMute as
@@ -1224,15 +1392,12 @@
 
     readOutputParameters_l();
 
-    // mStreamTypes[AUDIO_STREAM_CNT] is initialized by stream_type_t default constructor
-    // There is no AUDIO_STREAM_MIN, and ++ operator does not compile
+    // ++ operator does not compile
     for (audio_stream_type_t stream = AUDIO_STREAM_MIN; stream < AUDIO_STREAM_CNT;
             stream = (audio_stream_type_t) (stream + 1)) {
         mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
         mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
     }
-    // mStreamTypes[AUDIO_STREAM_CNT] exists but isn't explicitly initialized here,
-    // because mAudioFlinger doesn't have one to copy from
 }
 
 AudioFlinger::PlaybackThread::~PlaybackThread()
@@ -1317,7 +1482,10 @@
 
 void AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
 {
-    dprintf(fd, "\nOutput thread %p:\n", this);
+    dprintf(fd, "\nOutput thread %p type %d (%s):\n", this, type(), threadTypeToString(type()));
+
+    dumpBase(fd, args);
+
     dprintf(fd, "  Normal frame count: %zu\n", mNormalFrameCount);
     dprintf(fd, "  Last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
     dprintf(fd, "  Total writes: %d\n", mNumWrites);
@@ -1328,15 +1496,17 @@
     dprintf(fd, "  Mixer buffer: %p\n", mMixerBuffer);
     dprintf(fd, "  Effect buffer: %p\n", mEffectBuffer);
     dprintf(fd, "  Fast track availMask=%#x\n", mFastTrackAvailMask);
-
-    dumpBase(fd, args);
+    AudioStreamOut *output = mOutput;
+    audio_output_flags_t flags = output != NULL ? output->flags : AUDIO_OUTPUT_FLAG_NONE;
+    String8 flagsAsString = outputFlagsToString(flags);
+    dprintf(fd, "  AudioStreamOut: %p flags %#x (%s)\n", output, flags, flagsAsString.string());
 }
 
 // Thread virtuals
 
 void AudioFlinger::PlaybackThread::onFirstRef()
 {
-    run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
+    run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
 }
 
 // ThreadBase virtuals
@@ -1380,9 +1550,10 @@
               (
                 (sharedBuffer != 0)
               ) ||
-              // use case 2: callback handler and frame count is default or at least as large as HAL
+              // use case 2: frame count is default or at least as large as HAL
               (
-                (tid != -1) &&
+                // we formerly checked for a callback handler (non-0 tid),
+                // but that is no longer required for TRANSFER_OBTAIN mode
                 ((frameCount == 0) ||
                 (frameCount >= mFrameCount))
               )
@@ -1422,20 +1593,25 @@
                 audio_is_linear_pcm(format),
                 channelMask, sampleRate, mSampleRate, hasFastMixer(), tid, mFastTrackAvailMask);
         *flags &= ~IAudioFlinger::TRACK_FAST;
-        // For compatibility with AudioTrack calculation, buffer depth is forced
-        // to be at least 2 x the normal mixer frame count and cover audio hardware latency.
-        // This is probably too conservative, but legacy application code may depend on it.
-        // If you change this calculation, also review the start threshold which is related.
+      }
+    }
+    // For normal PCM streaming tracks, update minimum frame count.
+    // For compatibility with AudioTrack calculation, buffer depth is forced
+    // to be at least 2 x the normal mixer frame count and cover audio hardware latency.
+    // This is probably too conservative, but legacy application code may depend on it.
+    // If you change this calculation, also review the start threshold which is related.
+    if (!(*flags & IAudioFlinger::TRACK_FAST)
+            && audio_is_linear_pcm(format) && sharedBuffer == 0) {
         uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream);
         uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
         if (minBufCount < 2) {
             minBufCount = 2;
         }
-        size_t minFrameCount = mNormalFrameCount * minBufCount;
-        if (frameCount < minFrameCount) {
+        size_t minFrameCount =
+                minBufCount * sourceFramesNeeded(sampleRate, mNormalFrameCount, mSampleRate);
+        if (frameCount < minFrameCount) { // including frameCount == 0
             frameCount = minFrameCount;
         }
-      }
     }
     *pFrameCount = frameCount;
 
@@ -1625,13 +1801,15 @@
         if (track->isExternalTrack()) {
             TrackBase::track_state state = track->mState;
             mLock.unlock();
-            status = AudioSystem::startOutput(mId, track->streamType(), track->sessionId());
+            status = AudioSystem::startOutput(mId, track->streamType(),
+                                              (audio_session_t)track->sessionId());
             mLock.lock();
             // abort track was stopped/paused while we released the lock
             if (state != track->mState) {
                 if (status == NO_ERROR) {
                     mLock.unlock();
-                    AudioSystem::stopOutput(mId, track->streamType(), track->sessionId());
+                    AudioSystem::stopOutput(mId, track->streamType(),
+                                            (audio_session_t)track->sessionId());
                     mLock.lock();
                 }
                 return INVALID_OPERATION;
@@ -1848,6 +2026,35 @@
         }
     }
 
+    mHwSupportsPause = false;
+    if (mOutput->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
+        if (mOutput->stream->pause != NULL) {
+            if (mOutput->stream->resume != NULL) {
+                mHwSupportsPause = true;
+            } else {
+                ALOGW("direct output implements pause but not resume");
+            }
+        } else if (mOutput->stream->resume != NULL) {
+            ALOGW("direct output implements resume but not pause");
+        }
+    }
+
+    if (mType == DUPLICATING && mMixerBufferEnabled && mEffectBufferEnabled) {
+        // For best precision, we use float instead of the associated output
+        // device format (typically PCM 16 bit).
+
+        mFormat = AUDIO_FORMAT_PCM_FLOAT;
+        mFrameSize = mChannelCount * audio_bytes_per_sample(mFormat);
+        mBufferSize = mFrameSize * mFrameCount;
+
+        // TODO: We currently use the associated output device channel mask and sample rate.
+        // (1) Perhaps use the ORed channel mask of all downstream MixerThreads
+        // (if a valid mask) to avoid premature downmix.
+        // (2) Perhaps use the maximum sample rate of all downstream MixerThreads
+        // instead of the output device sample rate to avoid loss of high frequency information.
+        // This may need to be updated as MixerThread/OutputTracks are added and not here.
+    }
+
     // Calculate size of normal sink buffer relative to the HAL output buffer size
     double multiplier = 1.0;
     if (mType == MIXER && (kUseFastMixer == FastMixer_Static ||
@@ -2060,13 +2267,15 @@
         for (size_t i = 0 ; i < count ; i++) {
             const sp<Track>& track = tracksToRemove.itemAt(i);
             if (track->isExternalTrack()) {
-                AudioSystem::stopOutput(mId, track->streamType(), track->sessionId());
+                AudioSystem::stopOutput(mId, track->streamType(),
+                                        (audio_session_t)track->sessionId());
 #ifdef ADD_BATTERY_DATA
                 // to track the speaker usage
                 addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
 #endif
                 if (track->isTerminated()) {
-                    AudioSystem::releaseOutput(mId);
+                    AudioSystem::releaseOutput(mId, track->streamType(),
+                                               (audio_session_t)track->sessionId());
                 }
             }
         }
@@ -2180,7 +2389,13 @@
 
 void AudioFlinger::PlaybackThread::threadLoop_exit()
 {
-    // Default implementation has nothing to do
+    {
+        Mutex::Autolock _l(mLock);
+        for (size_t i = 0; i < mTracks.size(); i++) {
+            sp<Track> track = mTracks[i];
+            track->invalidate();
+        }
+    }
 }
 
 /*
@@ -2620,7 +2835,9 @@
                 }
 
             } else {
+                ATRACE_BEGIN("sleep");
                 usleep(sleepTime);
+                ATRACE_END();
             }
         }
 
@@ -2688,7 +2905,8 @@
     if (mNormalSink != 0) {
         return mNormalSink->getTimestamp(timestamp);
     }
-    if ((mType == OFFLOAD || mType == DIRECT) && mOutput->stream->get_presentation_position) {
+    if ((mType == OFFLOAD || mType == DIRECT)
+            && mOutput != NULL && mOutput->stream->get_presentation_position) {
         uint64_t position64;
         int ret = mOutput->stream->get_presentation_position(
                                                 mOutput->stream, &position64, &timestamp.mTime);
@@ -2779,6 +2997,12 @@
             mNormalFrameCount);
     mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
 
+    if (type == DUPLICATING) {
+        // The Duplicating thread uses the AudioMixer and delivers data to OutputTracks
+        // (downstream MixerThreads) in DuplicatingThread::threadLoop_write().
+        // Do not create or use mFastMixer, mOutputSink, mPipeSink, or mNormalSink.
+        return;
+    }
     // create an NBAIO sink for the HAL output stream, and negotiate
     mOutputSink = new AudioStreamOutSink(output->stream);
     size_t numCounterOffers = 0;
@@ -2820,6 +3044,7 @@
         NBAIO_Format format = mOutputSink->format();
         NBAIO_Format origformat = format;
         // adjust format to match that of the Fast Mixer
+        ALOGV("format changed from %d to %d", format.mFormat, fastMixerFormat);
         format.mFormat = fastMixerFormat;
         format.mFrameSize = audio_bytes_per_sample(format.mFormat) * format.mChannelCount;
 
@@ -2999,8 +3224,10 @@
 #endif
             }
             state->mCommand = FastMixerState::MIX_WRITE;
+#ifdef FAST_THREAD_STATISTICS
             mFastMixerDumpState.increaseSamplingN(mAudioFlinger->isLowRamDevice() ?
-                    FastMixerDumpState::kSamplingNforLowRamDevice : FastMixerDumpState::kSamplingN);
+                FastThreadDumpState::kSamplingNforLowRamDevice : FastThreadDumpState::kSamplingN);
+#endif
             sq->end();
             sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
             if (kUseFastMixer == FastMixer_Dynamic) {
@@ -3071,6 +3298,7 @@
         mCallbackThread->setWriteBlocked(mWriteAckSequence);
         mCallbackThread->setDraining(mDrainSequence);
     }
+    mHwPaused = false;
 }
 
 void AudioFlinger::PlaybackThread::onAddNewTrack_l()
@@ -3364,8 +3592,7 @@
         if (sr == mSampleRate) {
             desiredFrames = mNormalFrameCount;
         } else {
-            // +1 for rounding and +1 for additional sample needed for interpolation
-            desiredFrames = (mNormalFrameCount * sr) / mSampleRate + 1 + 1;
+            desiredFrames = sourceFramesNeeded(sr, mNormalFrameCount, mSampleRate);
             // add frames already consumed but not yet released by the resampler
             // because mAudioTrackServerProxy->framesReady() will include these frames
             desiredFrames += mAudioMixer->getUnreleasedFrames(track->name());
@@ -3383,6 +3610,23 @@
         }
 
         size_t framesReady = track->framesReady();
+        if (ATRACE_ENABLED()) {
+            // I wish we had formatted trace names
+            char traceName[16];
+            strcpy(traceName, "nRdy");
+            int name = track->name();
+            if (AudioMixer::TRACK0 <= name &&
+                    name < (int) (AudioMixer::TRACK0 + AudioMixer::MAX_NUM_TRACKS)) {
+                name -= AudioMixer::TRACK0;
+                traceName[4] = (name / 10) + '0';
+                traceName[5] = (name % 10) + '0';
+            } else {
+                traceName[4] = '?';
+                traceName[5] = '?';
+            }
+            traceName[6] = '\0';
+            ATRACE_INT(traceName, framesReady);
+        }
         if ((framesReady >= minFrames) && track->isReady() &&
                 !track->isPaused() && !track->isTerminated())
         {
@@ -3983,6 +4227,9 @@
 {
     size_t count = mActiveTracks.size();
     mixer_state mixerStatus = MIXER_IDLE;
+    bool doHwPause = false;
+    bool doHwResume = false;
+    bool flushPending = false;
 
     // find out which tracks need to be processed
     for (size_t i = 0; i < count; i++) {
@@ -4001,10 +4248,37 @@
         sp<Track> l = mLatestActiveTrack.promote();
         bool last = l.get() == track;
 
+        if (mHwSupportsPause && track->isPausing()) {
+            track->setPaused();
+            if (last && !mHwPaused) {
+                doHwPause = true;
+                mHwPaused = true;
+            }
+            tracksToRemove->add(track);
+        } else if (track->isFlushPending()) {
+            track->flushAck();
+            if (last) {
+                flushPending = true;
+            }
+        } else if (mHwSupportsPause && track->isResumePending()){
+            track->resumeAck();
+            if (last) {
+                if (mHwPaused) {
+                    doHwResume = true;
+                    mHwPaused = false;
+                }
+            }
+        }
+
         // The first time a track is added we wait
-        // for all its buffers to be filled before processing it
+        // for all its buffers to be filled before processing it.
+        // Allow draining the buffer in case the client
+        // app does not call stop() and relies on underrun to stop:
+        // hence the test on (track->mRetryCount > 1).
+        // If retryCount<=1 then track is about to underrun and be removed.
         uint32_t minFrames;
-        if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing()) {
+        if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing()
+            && (track->mRetryCount > 1)) {
             minFrames = mNormalFrameCount;
         } else {
             minFrames = 1;
@@ -4019,8 +4293,8 @@
                 track->mFillingUpStatus = Track::FS_ACTIVE;
                 // make sure processVolume_l() will apply new volume even if 0
                 mLeftVolFloat = mRightVolFloat = -1.0;
-                if (track->mState == TrackBase::RESUMING) {
-                    track->mState = TrackBase::ACTIVE;
+                if (!mHwSupportsPause) {
+                    track->resumeAck();
                 }
             }
 
@@ -4031,6 +4305,10 @@
                 track->mRetryCount = kMaxTrackRetriesDirect;
                 mActiveTrack = t;
                 mixerStatus = MIXER_TRACKS_READY;
+                if (usesHwAvSync() && mHwPaused) {
+                    doHwResume = true;
+                    mHwPaused = false;
+                }
             }
         } else {
             // clear effect chain input buffer if the last active track started underruns
@@ -4059,9 +4337,6 @@
                         track->mState = TrackBase::STOPPED;
                     }
                     if (track->isStopped()) {
-                        if (track->mState == TrackBase::FLUSHED) {
-                            flushHw_l();
-                        }
                         track->reset();
                     }
                     tracksToRemove->add(track);
@@ -4078,11 +4353,39 @@
                     android_atomic_or(CBLK_DISABLED, &cblk->mFlags);
                 } else if (last) {
                     mixerStatus = MIXER_TRACKS_ENABLED;
+                    if (usesHwAvSync() && !mHwPaused && !mStandby) {
+                        doHwPause = true;
+                        mHwPaused = true;
+                    }
                 }
             }
         }
     }
 
+    // if an active track did not command a flush, check for pending flush on stopped tracks
+    if (!flushPending) {
+        for (size_t i = 0; i < mTracks.size(); i++) {
+            if (mTracks[i]->isFlushPending()) {
+                mTracks[i]->flushAck();
+                flushPending = true;
+            }
+        }
+    }
+
+    // make sure the pause/flush/resume sequence is executed in the right order.
+    // If a flush is pending and a track is active but the HW is not paused, force a HW pause
+    // before flush and then resume HW. This can happen in case of pause/flush/resume
+    // if resume is received before pause is executed.
+    if (mHwSupportsPause && !mStandby &&
+            (doHwPause || (flushPending && !mHwPaused && (count != 0)))) {
+        mOutput->stream->pause(mOutput->stream);
+    }
+    if (flushPending) {
+        flushHw_l();
+    }
+    if (mHwSupportsPause && !mStandby && doHwResume) {
+        mOutput->stream->resume(mOutput->stream);
+    }
     // remove all the tracks that need to be...
     removeTracks_l(*tracksToRemove);
 
@@ -4115,6 +4418,11 @@
 
 void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
 {
+    // do not write to HAL when paused
+    if (mHwPaused || (usesHwAvSync() && mStandby)) {
+        sleepTime = idleSleepTime;
+        return;
+    }
     if (sleepTime == 0) {
         if (mMixerStatus == MIXER_TRACKS_ENABLED) {
             sleepTime = activeSleepTime;
@@ -4127,6 +4435,38 @@
     }
 }
 
+void AudioFlinger::DirectOutputThread::threadLoop_exit()
+{
+    {
+        Mutex::Autolock _l(mLock);
+        bool flushPending = false;
+        for (size_t i = 0; i < mTracks.size(); i++) {
+            if (mTracks[i]->isFlushPending()) {
+                mTracks[i]->flushAck();
+                flushPending = true;
+            }
+        }
+        if (flushPending) {
+            flushHw_l();
+        }
+    }
+    PlaybackThread::threadLoop_exit();
+}
+
+// must be called with thread mutex locked
+bool AudioFlinger::DirectOutputThread::shouldStandby_l()
+{
+    bool trackPaused = false;
+
+    // do not put the HAL in standby when paused. AwesomePlayer clear the offloaded AudioTrack
+    // after a timeout and we will enter standby then.
+    if (mTracks.size() > 0) {
+        trackPaused = mTracks[mTracks.size() - 1]->isPaused();
+    }
+
+    return !mStandby && !(trackPaused || (usesHwAvSync() && mHwPaused));
+}
+
 // getTrackName_l() must be called with ThreadBase::mLock held
 int AudioFlinger::DirectOutputThread::getTrackName_l(audio_channel_mask_t channelMask __unused,
         audio_format_t format __unused, int sessionId __unused)
@@ -4236,8 +4576,10 @@
 
 void AudioFlinger::DirectOutputThread::flushHw_l()
 {
-    if (mOutput->stream->flush != NULL)
+    if (mOutput->stream->flush != NULL) {
         mOutput->stream->flush(mOutput->stream);
+    }
+    mHwPaused = false;
 }
 
 // ----------------------------------------------------------------------------
@@ -4346,8 +4688,6 @@
 AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
         AudioStreamOut* output, audio_io_handle_t id, uint32_t device)
     :   DirectOutputThread(audioFlinger, output, id, device, OFFLOAD),
-        mHwPaused(false),
-        mFlushPending(false),
         mPausedBytesRemaining(0)
 {
     //FIXME: mStandby should be set to true by ThreadBase constructor
@@ -4584,21 +4924,6 @@
     return false;
 }
 
-// must be called with thread mutex locked
-bool AudioFlinger::OffloadThread::shouldStandby_l()
-{
-    bool trackPaused = false;
-
-    // do not put the HAL in standby when paused. AwesomePlayer clear the offloaded AudioTrack
-    // after a timeout and we will enter standby then.
-    if (mTracks.size() > 0) {
-        trackPaused = mTracks[mTracks.size() - 1]->isPaused();
-    }
-
-    return !mStandby && !trackPaused;
-}
-
-
 bool AudioFlinger::OffloadThread::waitingAsyncCallback()
 {
     Mutex::Autolock _l(mLock);
@@ -4613,7 +4938,6 @@
     mBytesRemaining = 0;
     mPausedWriteLength = 0;
     mPausedBytesRemaining = 0;
-    mHwPaused = false;
 
     if (mUseAsyncWrite) {
         // discard any pending drain or write ack by incrementing sequence
@@ -4661,7 +4985,11 @@
     if (outputsReady(outputTracks)) {
         mAudioMixer->process(AudioBufferProvider::kInvalidPTS);
     } else {
-        memset(mSinkBuffer, 0, mSinkBufferSize);
+        if (mMixerBufferValid) {
+            memset(mMixerBuffer, 0, mMixerBufferSize);
+        } else {
+            memset(mSinkBuffer, 0, mSinkBufferSize);
+        }
     }
     sleepTime = 0;
     writeFrames = mNormalFrameCount;
@@ -4692,15 +5020,7 @@
 ssize_t AudioFlinger::DuplicatingThread::threadLoop_write()
 {
     for (size_t i = 0; i < outputTracks.size(); i++) {
-        // We convert the duplicating thread format to AUDIO_FORMAT_PCM_16_BIT
-        // for delivery downstream as needed. This in-place conversion is safe as
-        // AUDIO_FORMAT_PCM_16_BIT is smaller than any other supported format
-        // (AUDIO_FORMAT_PCM_8_BIT is not allowed here).
-        if (mFormat != AUDIO_FORMAT_PCM_16_BIT) {
-            memcpy_by_audio_format(mSinkBuffer, AUDIO_FORMAT_PCM_16_BIT,
-                    mSinkBuffer, mFormat, writeFrames * mChannelCount);
-        }
-        outputTracks[i]->write(reinterpret_cast<int16_t*>(mSinkBuffer), writeFrames);
+        outputTracks[i]->write(mSinkBuffer, writeFrames);
     }
     mStandby = false;
     return (ssize_t)mSinkBufferSize;
@@ -4727,25 +5047,26 @@
 void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
 {
     Mutex::Autolock _l(mLock);
-    // FIXME explain this formula
-    size_t frameCount = (3 * mNormalFrameCount * mSampleRate) / thread->sampleRate();
-    // OutputTrack is forced to AUDIO_FORMAT_PCM_16_BIT regardless of mFormat
-    // due to current usage case and restrictions on the AudioBufferProvider.
-    // Actual buffer conversion is done in threadLoop_write().
-    //
-    // TODO: This may change in the future, depending on multichannel
-    // (and non int16_t*) support on AF::PlaybackThread::OutputTrack
-    OutputTrack *outputTrack = new OutputTrack(thread,
+    // The downstream MixerThread consumes thread->frameCount() amount of frames per mix pass.
+    // Adjust for thread->sampleRate() to determine minimum buffer frame count.
+    // Then triple buffer because Threads do not run synchronously and may not be clock locked.
+    const size_t frameCount =
+            3 * sourceFramesNeeded(mSampleRate, thread->frameCount(), thread->sampleRate());
+    // TODO: Consider asynchronous sample rate conversion to handle clock disparity
+    // from different OutputTracks and their associated MixerThreads (e.g. one may
+    // nearly empty and the other may be dropping data).
+
+    sp<OutputTrack> outputTrack = new OutputTrack(thread,
                                             this,
                                             mSampleRate,
-                                            AUDIO_FORMAT_PCM_16_BIT,
+                                            mFormat,
                                             mChannelMask,
                                             frameCount,
                                             IPCThreadState::self()->getCallingUid());
     if (outputTrack->cblk() != NULL) {
-        thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
+        thread->setStreamVolume(AUDIO_STREAM_PATCH, 1.0f);
         mOutputTracks.add(outputTrack);
-        ALOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
+        ALOGV("addOutputTrack() track %p, on thread %p", outputTrack.get(), thread);
         updateWaitTime_l();
     }
 }
@@ -4846,8 +5167,8 @@
     // mFastCaptureNBLogWriter
     , mFastTrackAvail(false)
 {
-    snprintf(mName, kNameLength, "AudioIn_%X", id);
-    mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mName);
+    snprintf(mThreadName, kThreadNameLength, "AudioIn_%X", id);
+    mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
 
     readInputParameters_l();
 
@@ -4988,7 +5309,7 @@
 
 void AudioFlinger::RecordThread::onFirstRef()
 {
-    run(mName, PRIORITY_URGENT_AUDIO);
+    run(mThreadName, PRIORITY_URGENT_AUDIO);
 }
 
 bool AudioFlinger::RecordThread::threadLoop()
@@ -5029,7 +5350,9 @@
 
         // sleep with mutex unlocked
         if (sleepUs > 0) {
+            ATRACE_BEGIN("sleep");
             usleep(sleepUs);
+            ATRACE_END();
             sleepUs = 0;
         }
 
@@ -5173,7 +5496,8 @@
                 state->mCommand = FastCaptureState::READ_WRITE;
 #if 0   // FIXME
                 mFastCaptureDumpState.increaseSamplingN(mAudioFlinger->isLowRamDevice() ?
-                        FastCaptureDumpState::kSamplingNforLowRamDevice : FastMixerDumpState::kSamplingN);
+                        FastThreadDumpState::kSamplingNforLowRamDevice :
+                        FastThreadDumpState::kSamplingN);
 #endif
                 didModify = true;
             }
@@ -5321,8 +5645,8 @@
                             upmix_to_stereo_i16_from_mono_i16((int16_t *)dst, (const int16_t *)src,
                                     part1);
                         } else {
-                            downmix_to_mono_i16_from_stereo_i16((int16_t *)dst, (const int16_t *)src,
-                                    part1);
+                            downmix_to_mono_i16_from_stereo_i16((int16_t *)dst,
+                                    (const int16_t *)src, part1);
                         }
                         dst += part1 * activeTrack->mFrameSize;
                         front += part1;
@@ -5833,15 +6157,17 @@
 {
     dprintf(fd, "\nInput thread %p:\n", this);
 
-    if (mActiveTracks.size() > 0) {
-        dprintf(fd, "  Buffer size: %zu bytes\n", mBufferSize);
-    } else {
+    dumpBase(fd, args);
+
+    if (mActiveTracks.size() == 0) {
         dprintf(fd, "  No active record clients\n");
     }
     dprintf(fd, "  Fast capture thread: %s\n", hasFastCapture() ? "yes" : "no");
     dprintf(fd, "  Fast track available: %s\n", mFastTrackAvail ? "yes" : "no");
 
-    dumpBase(fd, args);
+    //  Make a non-atomic copy of fast capture dump state so it won't change underneath us
+    const FastCaptureDumpState copy(mFastCaptureDumpState);
+    copy.dump(fd);
 }
 
 void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args __unused)
@@ -6306,4 +6632,4 @@
     config->ext.mix.usecase.source = mAudioSource;
 }
 
-}; // namespace android
+} // namespace android
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index bb9aa18..d600ea9 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -32,6 +32,8 @@
         OFFLOAD             // Thread class is OffloadThread
     };
 
+    static const char *threadTypeToString(type_t type);
+
     ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
                 audio_devices_t outDevice, audio_devices_t inDevice, type_t type);
     virtual             ~ThreadBase();
@@ -406,6 +408,7 @@
                 audio_channel_mask_t    mChannelMask;
                 uint32_t                mChannelCount;
                 size_t                  mFrameSize;
+                // not HAL frame size, this is for output sink (to pipe to fast mixer)
                 audio_format_t          mFormat;           // Source format for Recording and
                                                            // Sink format for Playback.
                                                            // Sink format may be different than
@@ -424,13 +427,13 @@
                 bool                    mStandby;     // Whether thread is currently in standby.
                 audio_devices_t         mOutDevice;   // output device
                 audio_devices_t         mInDevice;    // input device
-                audio_source_t          mAudioSource; // (see audio.h, audio_source_t)
+                audio_source_t          mAudioSource;
 
                 const audio_io_handle_t mId;
                 Vector< sp<EffectChain> > mEffectChains;
 
-                static const int        kNameLength = 16;   // prctl(PR_SET_NAME) limit
-                char                    mName[kNameLength];
+                static const int        kThreadNameLength = 16; // prctl(PR_SET_NAME) limit
+                char                    mThreadName[kThreadNameLength]; // guaranteed NUL-terminated
                 sp<IPowerManager>       mPowerManager;
                 sp<IBinder>             mWakeLockToken;
                 const sp<PMDeathRecipient> mDeathRecipient;
@@ -710,6 +713,9 @@
                                    audio_patch_handle_t *handle);
     virtual     status_t    releaseAudioPatch_l(const audio_patch_handle_t handle);
 
+                bool        usesHwAvSync() const { return (mType == DIRECT) && (mOutput != NULL) &&
+                                                (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); }
+
 private:
 
     friend class AudioFlinger;      // for numerous
@@ -727,9 +733,7 @@
     void        dumpTracks(int fd, const Vector<String16>& args);
 
     SortedVector< sp<Track> >       mTracks;
-    // mStreamTypes[] uses 1 additional stream type internally for the OutputTrack used by
-    // DuplicatingThread
-    stream_type_t                   mStreamTypes[AUDIO_STREAM_CNT + 1];
+    stream_type_t                   mStreamTypes[AUDIO_STREAM_CNT];
     AudioStreamOut                  *mOutput;
 
     float                           mMasterVolume;
@@ -811,7 +815,9 @@
 protected:
                 // accessed by both binder threads and within threadLoop(), lock on mutex needed
                 unsigned    mFastTrackAvailMask;    // bit i set if fast track [i] is available
-
+                bool        mHwSupportsPause;
+                bool        mHwPaused;
+                bool        mFlushPending;
 private:
     // timestamp latch:
     //  D input is written by threadLoop_write while mutex is unlocked, and read while locked
@@ -912,6 +918,8 @@
     virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
     virtual     void        threadLoop_mix();
     virtual     void        threadLoop_sleepTime();
+    virtual     void        threadLoop_exit();
+    virtual     bool        shouldStandby_l();
 
     // volumes last sent to audio HAL with stream->set_volume()
     float mLeftVolFloat;
@@ -942,12 +950,9 @@
 
     virtual     bool        waitingAsyncCallback();
     virtual     bool        waitingAsyncCallback_l();
-    virtual     bool        shouldStandby_l();
     virtual     void        onAddNewTrack_l();
 
 private:
-    bool        mHwPaused;
-    bool        mFlushPending;
     size_t      mPausedWriteLength;     // length in bytes of write interrupted by pause
     size_t      mPausedBytesRemaining;  // bytes still waiting in mixbuffer after resume
     wp<Track>   mPreviousTrack;         // used to detect track switch
@@ -1165,7 +1170,8 @@
             const sp<MemoryDealer>              mReadOnlyHeap;
 
             // one-time initialization, no locks required
-            sp<FastCapture>                     mFastCapture;   // non-0 if there is also a fast capture
+            sp<FastCapture>                     mFastCapture;   // non-0 if there is also
+                                                                // a fast capture
             // FIXME audio watchdog thread
 
             // contents are not guaranteed to be consistent, no locks required
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 7d8d4c8..38667b9 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -20,6 +20,7 @@
 //#define LOG_NDEBUG 0
 
 #include "Configuration.h"
+#include <linux/futex.h>
 #include <math.h>
 #include <sys/syscall.h>
 #include <utils/Log.h>
@@ -443,8 +444,6 @@
         //       this means we are potentially denying other more important fast tracks from
         //       being created.  It would be better to allocate the index dynamically.
         mFastIndex = i;
-        // Read the initial underruns because this field is never cleared by the fast mixer
-        mObservedUnderruns = thread->getFastTrackUnderruns(i);
         thread->mFastTrackAvailMask &= ~(1 << i);
     }
 }
@@ -491,7 +490,7 @@
             wasActive = playbackThread->destroyTrack_l(this);
         }
         if (isExternalTrack() && !wasActive) {
-            AudioSystem::releaseOutput(mThreadIoHandle);
+            AudioSystem::releaseOutput(mThreadIoHandle, mStreamType, (audio_session_t)mSessionId);
         }
     }
 }
@@ -611,15 +610,16 @@
 
 // ExtendedAudioBufferProvider interface
 
-// Note that framesReady() takes a mutex on the control block using tryLock().
-// This could result in priority inversion if framesReady() is called by the normal mixer,
-// as the normal mixer thread runs at lower
-// priority than the client's callback thread:  there is a short window within framesReady()
-// during which the normal mixer could be preempted, and the client callback would block.
-// Another problem can occur if framesReady() is called by the fast mixer:
-// the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer.
-// FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue.
+// framesReady() may return an approximation of the number of frames if called
+// from a different thread than the one calling Proxy->obtainBuffer() and
+// Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
+// AudioTrackServerProxy so be especially careful calling with FastTracks.
 size_t AudioFlinger::PlaybackThread::Track::framesReady() const {
+    if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
+        // Static tracks return zero frames immediately upon stopping (for FastTracks).
+        // The remainder of the buffer is not drained.
+        return 0;
+    }
     return mAudioTrackServerProxy->framesReady();
 }
 
@@ -692,6 +692,12 @@
         }
 
         PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        if (isFastTrack()) {
+            // refresh fast track underruns on start because that field is never cleared
+            // by the fast mixer; furthermore, the same track can be recycled, i.e. start
+            // after stop.
+            mObservedUnderruns = playbackThread->getFastTrackUnderruns(mFastIndex);
+        }
         status = playbackThread->addTrack_l(this);
         if (status == INVALID_OPERATION || status == PERMISSION_DENIED) {
             triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
@@ -822,12 +828,11 @@
             // this will be done by prepareTracks_l() when the track is stopped.
             // prepareTracks_l() will see mState == FLUSHED, then
             // remove from active track list, reset(), and trigger presentation complete
+            if (isDirect()) {
+                mFlushHwPending = true;
+            }
             if (playbackThread->mActiveTracks.indexOf(this) < 0) {
                 reset();
-                if (thread->type() == ThreadBase::DIRECT) {
-                    DirectOutputThread *t = (DirectOutputThread *)playbackThread;
-                    t->flushHw_l();
-                }
             }
         }
         // Prevent flush being lost if the track is flushed and then resumed
@@ -840,7 +845,7 @@
 // must be called with thread lock held
 void AudioFlinger::PlaybackThread::Track::flushAck()
 {
-    if (!isOffloaded())
+    if (!isOffloaded() && !isDirect())
         return;
 
     mFlushHwPending = false;
@@ -1657,8 +1662,9 @@
             audio_channel_mask_t channelMask,
             size_t frameCount,
             int uid)
-    :   Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
-                NULL, 0, 0, uid, IAudioFlinger::TRACK_DEFAULT, TYPE_OUTPUT),
+    :   Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
+              sampleRate, format, channelMask, frameCount,
+              NULL, 0, 0, uid, IAudioFlinger::TRACK_DEFAULT, TYPE_OUTPUT),
     mActive(false), mSourceThread(sourceThread), mClientProxy(NULL)
 {
 
@@ -1709,36 +1715,18 @@
     mActive = false;
 }
 
-bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
+bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frames)
 {
     Buffer *pInBuffer;
     Buffer inBuffer;
-    uint32_t channelCount = mChannelCount;
     bool outputBufferFull = false;
     inBuffer.frameCount = frames;
-    inBuffer.i16 = data;
+    inBuffer.raw = data;
 
     uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
 
     if (!mActive && frames != 0) {
-        start();
-        sp<ThreadBase> thread = mThread.promote();
-        if (thread != 0) {
-            MixerThread *mixerThread = (MixerThread *)thread.get();
-            if (mFrameCount > frames) {
-                if (mBufferQueue.size() < kMaxOverFlowBuffers) {
-                    uint32_t startFrames = (mFrameCount - frames);
-                    pInBuffer = new Buffer;
-                    pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
-                    pInBuffer->frameCount = startFrames;
-                    pInBuffer->i16 = pInBuffer->mBuffer;
-                    memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
-                    mBufferQueue.add(pInBuffer);
-                } else {
-                    ALOGW("OutputTrack::write() %p no more buffers in queue", this);
-                }
-            }
-        }
+        (void) start();
     }
 
     while (waitTimeLeftMs) {
@@ -1773,20 +1761,20 @@
 
         uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
                 pInBuffer->frameCount;
-        memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
+        memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * mFrameSize);
         Proxy::Buffer buf;
         buf.mFrameCount = outFrames;
         buf.mRaw = NULL;
         mClientProxy->releaseBuffer(&buf);
         pInBuffer->frameCount -= outFrames;
-        pInBuffer->i16 += outFrames * channelCount;
+        pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
         mOutBuffer.frameCount -= outFrames;
-        mOutBuffer.i16 += outFrames * channelCount;
+        mOutBuffer.raw = (int8_t *)mOutBuffer.raw + outFrames * mFrameSize;
 
         if (pInBuffer->frameCount == 0) {
             if (mBufferQueue.size()) {
                 mBufferQueue.removeAt(0);
-                delete [] pInBuffer->mBuffer;
+                free(pInBuffer->mBuffer);
                 delete pInBuffer;
                 ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this,
                         mThread.unsafe_get(), mBufferQueue.size());
@@ -1802,11 +1790,10 @@
         if (thread != 0 && !thread->standby()) {
             if (mBufferQueue.size() < kMaxOverFlowBuffers) {
                 pInBuffer = new Buffer;
-                pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
+                pInBuffer->mBuffer = malloc(inBuffer.frameCount * mFrameSize);
                 pInBuffer->frameCount = inBuffer.frameCount;
-                pInBuffer->i16 = pInBuffer->mBuffer;
-                memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount *
-                        sizeof(int16_t));
+                pInBuffer->raw = pInBuffer->mBuffer;
+                memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
                 mBufferQueue.add(pInBuffer);
                 ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this,
                         mThread.unsafe_get(), mBufferQueue.size());
@@ -1817,23 +1804,10 @@
         }
     }
 
-    // Calling write() with a 0 length buffer, means that no more data will be written:
-    // If no more buffers are pending, fill output track buffer to make sure it is started
-    // by output mixer.
-    if (frames == 0 && mBufferQueue.size() == 0) {
-        // FIXME borken, replace by getting framesReady() from proxy
-        size_t user = 0;    // was mCblk->user
-        if (user < mFrameCount) {
-            frames = mFrameCount - user;
-            pInBuffer = new Buffer;
-            pInBuffer->mBuffer = new int16_t[frames * channelCount];
-            pInBuffer->frameCount = frames;
-            pInBuffer->i16 = pInBuffer->mBuffer;
-            memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
-            mBufferQueue.add(pInBuffer);
-        } else if (mActive) {
-            stop();
-        }
+    // Calling write() with a 0 length buffer means that no more data will be written:
+    // We rely on stop() to set the appropriate flags to allow the remaining frames to play out.
+    if (frames == 0 && mBufferQueue.size() == 0 && mActive) {
+        stop();
     }
 
     return outputBufferFull;
@@ -1859,7 +1833,7 @@
 
     for (size_t i = 0; i < size; i++) {
         Buffer *pBuffer = mBufferQueue.itemAt(i);
-        delete [] pBuffer->mBuffer;
+        free(pBuffer->mBuffer);
         delete pBuffer;
     }
     mBufferQueue.clear();
@@ -1873,7 +1847,8 @@
                                                      size_t frameCount,
                                                      void *buffer,
                                                      IAudioFlinger::track_flags_t flags)
-    :   Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount,
+    :   Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
+              sampleRate, format, channelMask, frameCount,
               buffer, 0, 0, getuid(), flags, TYPE_PATCH),
               mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true))
 {
@@ -2211,4 +2186,4 @@
     mProxy->releaseBuffer(buffer);
 }
 
-}; // namespace android
+} // namespace android
diff --git a/services/audioflinger/test-resample.cpp b/services/audioflinger/test-resample.cpp
index 84a655a..7893778 100644
--- a/services/audioflinger/test-resample.cpp
+++ b/services/audioflinger/test-resample.cpp
@@ -427,6 +427,14 @@
         printf("quality: %d  channels: %d  msec: %" PRId64 "  Mfrms/s: %.2lf\n",
                 quality, channels, time/1000000, output_frames * looplimit / (time / 1e9) / 1e6);
         resampler->reset();
+
+        // TODO fix legacy bug: reset does not clear buffers.
+        // delete and recreate resampler here.
+        delete resampler;
+        resampler = AudioResampler::create(format, channels,
+                    output_freq, quality);
+        resampler->setSampleRate(input_freq);
+        resampler->setVolume(AudioResampler::UNITY_GAIN_FLOAT, AudioResampler::UNITY_GAIN_FLOAT);
     }
 
     memset(output_vaddr, 0, output_size);
diff --git a/services/audioflinger/tests/Android.mk b/services/audioflinger/tests/Android.mk
index 7bba05b..8604ef5 100644
--- a/services/audioflinger/tests/Android.mk
+++ b/services/audioflinger/tests/Android.mk
@@ -10,19 +10,10 @@
 	liblog \
 	libutils \
 	libcutils \
-	libstlport \
 	libaudioutils \
 	libaudioresampler
 
-LOCAL_STATIC_LIBRARIES := \
-	libgtest \
-	libgtest_main
-
 LOCAL_C_INCLUDES := \
-	bionic \
-	bionic/libstdc++/include \
-	external/gtest/include \
-	external/stlport/stlport \
 	$(call include-path-for, audio-utils) \
 	frameworks/av/services/audioflinger
 
@@ -32,21 +23,24 @@
 LOCAL_MODULE := resampler_tests
 LOCAL_MODULE_TAGS := tests
 
-include $(BUILD_EXECUTABLE)
+include $(BUILD_NATIVE_TEST)
 
 #
 # audio mixer test tool
 #
 include $(CLEAR_VARS)
 
+# Clang++ aborts on AudioMixer.cpp,
+# b/18373866, "do not know how to split this operator."
+ifeq ($(filter $(TARGET_ARCH),arm arm64),$(TARGET_ARCH))
+    LOCAL_CLANG := false
+endif
+
 LOCAL_SRC_FILES:= \
 	test-mixer.cpp \
 	../AudioMixer.cpp.arm \
 
 LOCAL_C_INCLUDES := \
-	bionic \
-	bionic/libstdc++/include \
-	external/stlport/stlport \
 	$(call include-path-for, audio-effects) \
 	$(call include-path-for, audio-utils) \
 	frameworks/av/services/audioflinger
@@ -55,7 +49,6 @@
 	libsndfile
 
 LOCAL_SHARED_LIBRARIES := \
-	libstlport \
 	libeffects \
 	libnbaio \
 	libcommon_time_client \
@@ -70,4 +63,6 @@
 
 LOCAL_MODULE_TAGS := optional
 
+LOCAL_CXX_STL := libc++
+
 include $(BUILD_EXECUTABLE)
diff --git a/services/audioflinger/tests/build_and_run_all_unit_tests.sh b/services/audioflinger/tests/build_and_run_all_unit_tests.sh
index 2c453b0..7f4d456 100755
--- a/services/audioflinger/tests/build_and_run_all_unit_tests.sh
+++ b/services/audioflinger/tests/build_and_run_all_unit_tests.sh
@@ -15,7 +15,7 @@
 echo "waiting for device"
 adb root && adb wait-for-device remount
 adb push $OUT/system/lib/libaudioresampler.so /system/lib
-adb push $OUT/system/bin/resampler_tests /system/bin
+adb push $OUT/data/nativetest/resampler_tests /system/bin
 
 sh $ANDROID_BUILD_TOP/frameworks/av/services/audioflinger/tests/run_all_unit_tests.sh
 
diff --git a/services/audioflinger/tests/mixer_to_wav_tests.sh b/services/audioflinger/tests/mixer_to_wav_tests.sh
index e60e6d5..d0482a1 100755
--- a/services/audioflinger/tests/mixer_to_wav_tests.sh
+++ b/services/audioflinger/tests/mixer_to_wav_tests.sh
@@ -60,7 +60,7 @@
     fi
 
 # Test:
-# process__genericResampling
+# process__genericResampling with mixed integer and float track input
 # track__Resample / track__genericResample
     adb shell test-mixer $1 -s 48000 \
         -o /sdcard/tm48000grif.wav \
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index 6512c38..351ed79 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -3,19 +3,19 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    AudioPolicyService.cpp \
-    AudioPolicyEffects.cpp
+    service/AudioPolicyService.cpp \
+    service/AudioPolicyEffects.cpp
 
 ifeq ($(USE_LEGACY_AUDIO_POLICY), 1)
 LOCAL_SRC_FILES += \
-    AudioPolicyInterfaceImplLegacy.cpp \
-    AudioPolicyClientImplLegacy.cpp
+    service/AudioPolicyInterfaceImplLegacy.cpp \
+    service/AudioPolicyClientImplLegacy.cpp
 
     LOCAL_CFLAGS += -DUSE_LEGACY_AUDIO_POLICY
 else
 LOCAL_SRC_FILES += \
-    AudioPolicyInterfaceImpl.cpp \
-    AudioPolicyClientImpl.cpp
+    service/AudioPolicyInterfaceImpl.cpp \
+    service/AudioPolicyClientImpl.cpp
 endif
 
 LOCAL_C_INCLUDES := \
@@ -30,7 +30,8 @@
     libbinder \
     libmedia \
     libhardware \
-    libhardware_legacy
+    libhardware_legacy \
+    libserviceutility
 
 ifneq ($(USE_LEGACY_AUDIO_POLICY), 1)
 LOCAL_SHARED_LIBRARIES += \
@@ -38,8 +39,7 @@
 endif
 
 LOCAL_STATIC_LIBRARIES := \
-    libmedia_helper \
-    libserviceutility
+    libmedia_helper
 
 LOCAL_MODULE:= libaudiopolicyservice
 
@@ -53,7 +53,15 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    AudioPolicyManager.cpp
+    managerdefault/AudioPolicyManager.cpp \
+    managerdefault/ConfigParsingUtils.cpp \
+    managerdefault/Devices.cpp \
+    managerdefault/Gains.cpp \
+    managerdefault/HwModule.cpp \
+    managerdefault/IOProfile.cpp \
+    managerdefault/Ports.cpp \
+    managerdefault/AudioInputDescriptor.cpp \
+    managerdefault/AudioOutputDescriptor.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
@@ -73,7 +81,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    AudioPolicyFactory.cpp
+    manager/AudioPolicyFactory.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libaudiopolicymanagerdefault
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 5524463..116d0d6 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -18,6 +18,7 @@
 #define ANDROID_AUDIOPOLICY_INTERFACE_H
 
 #include <media/AudioSystem.h>
+#include <media/AudioPolicy.h>
 #include <utils/String8.h>
 
 #include <hardware/audio_policy.h>
@@ -56,6 +57,16 @@
 {
 
 public:
+    typedef enum {
+        API_INPUT_INVALID = -1,
+        API_INPUT_LEGACY  = 0,// e.g. audio recording from a microphone
+        API_INPUT_MIX_CAPTURE,// used for "remote submix", capture of the media to play it remotely
+        API_INPUT_MIX_EXT_POLICY_REROUTE,// used for platform audio rerouting, where mixes are
+                                         // handled by external and dynamically installed
+                                         // policies which reroute audio mixes
+    } input_type_t;
+
+public:
     virtual ~AudioPolicyInterface() {}
     //
     // configuration functions
@@ -64,7 +75,8 @@
     // indicate a change in device connection status
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
-                                          const char *device_address) = 0;
+                                              const char *device_address,
+                                              const char *device_name) = 0;
     // retrieve a device connection status
     virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                           const char *device_address) = 0;
@@ -90,30 +102,37 @@
                                         audio_channel_mask_t channelMask,
                                         audio_output_flags_t flags,
                                         const audio_offload_info_t *offloadInfo) = 0;
-    virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
-                                                uint32_t samplingRate,
-                                                audio_format_t format,
-                                                audio_channel_mask_t channelMask,
-                                                audio_output_flags_t flags,
-                                                const audio_offload_info_t *offloadInfo) = 0;
+    virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+                                        audio_io_handle_t *output,
+                                        audio_session_t session,
+                                        audio_stream_type_t *stream,
+                                        uint32_t samplingRate,
+                                        audio_format_t format,
+                                        audio_channel_mask_t channelMask,
+                                        audio_output_flags_t flags,
+                                        const audio_offload_info_t *offloadInfo) = 0;
     // indicates to the audio policy manager that the output starts being used by corresponding stream.
     virtual status_t startOutput(audio_io_handle_t output,
                                  audio_stream_type_t stream,
-                                 int session = 0) = 0;
+                                 audio_session_t session) = 0;
     // indicates to the audio policy manager that the output stops being used by corresponding stream.
     virtual status_t stopOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
-                                int session = 0) = 0;
+                                audio_session_t session) = 0;
     // releases the output.
-    virtual void releaseOutput(audio_io_handle_t output) = 0;
+    virtual void releaseOutput(audio_io_handle_t output,
+                               audio_stream_type_t stream,
+                               audio_session_t session) = 0;
 
     // request an input appropriate for record from the supplied device with supplied parameters.
-    virtual audio_io_handle_t getInput(audio_source_t inputSource,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_session_t session,
-                                    audio_input_flags_t flags) = 0;
+    virtual status_t getInputForAttr(const audio_attributes_t *attr,
+                                     audio_io_handle_t *input,
+                                     audio_session_t session,
+                                     uint32_t samplingRate,
+                                     audio_format_t format,
+                                     audio_channel_mask_t channelMask,
+                                     audio_input_flags_t flags,
+                                     input_type_t *inputType) = 0;
     // indicates to the audio policy manager that the input starts being used.
     virtual status_t startInput(audio_io_handle_t input,
                                 audio_session_t session) = 0;
@@ -195,6 +214,9 @@
                                            audio_devices_t *device) = 0;
 
     virtual status_t releaseSoundTriggerSession(audio_session_t session) = 0;
+
+    virtual status_t registerPolicyMixes(Vector<AudioMix> mixes) = 0;
+    virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes) = 0;
 };
 
 
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
deleted file mode 100644
index 50d7831..0000000
--- a/services/audiopolicy/AudioPolicyManager.h
+++ /dev/null
@@ -1,879 +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.
- */
-
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <cutils/config_utils.h>
-#include <cutils/misc.h>
-#include <utils/Timers.h>
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/SortedVector.h>
-#include "AudioPolicyInterface.h"
-
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-// Attenuation applied to STRATEGY_SONIFICATION streams when a headset is connected: 6dB
-#define SONIFICATION_HEADSET_VOLUME_FACTOR 0.5
-// Min volume for STRATEGY_SONIFICATION streams when limited by music volume: -36dB
-#define SONIFICATION_HEADSET_VOLUME_MIN  0.016
-// Time in milliseconds during which we consider that music is still active after a music
-// track was stopped - see computeVolume()
-#define SONIFICATION_HEADSET_MUSIC_DELAY  5000
-// Time in milliseconds after media stopped playing during which we consider that the
-// sonification should be as unobtrusive as during the time media was playing.
-#define SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY 5000
-// Time in milliseconds during witch some streams are muted while the audio path
-// is switched
-#define MUTE_TIME_MS 2000
-
-#define NUM_TEST_OUTPUTS 5
-
-#define NUM_VOL_CURVE_KNEES 2
-
-// Default minimum length allowed for offloading a compressed track
-// Can be overridden by the audio.offload.min.duration.secs property
-#define OFFLOAD_DEFAULT_MIN_DURATION_SECS 60
-
-#define MAX_MIXER_SAMPLING_RATE 48000
-#define MAX_MIXER_CHANNEL_COUNT 8
-
-// ----------------------------------------------------------------------------
-// AudioPolicyManager implements audio policy manager behavior common to all platforms.
-// ----------------------------------------------------------------------------
-
-class AudioPolicyManager: public AudioPolicyInterface
-#ifdef AUDIO_POLICY_TEST
-    , public Thread
-#endif //AUDIO_POLICY_TEST
-{
-
-public:
-                AudioPolicyManager(AudioPolicyClientInterface *clientInterface);
-        virtual ~AudioPolicyManager();
-
-        // AudioPolicyInterface
-        virtual status_t setDeviceConnectionState(audio_devices_t device,
-                                                          audio_policy_dev_state_t state,
-                                                          const char *device_address);
-        virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
-                                                                              const char *device_address);
-        virtual void setPhoneState(audio_mode_t state);
-        virtual void setForceUse(audio_policy_force_use_t usage,
-                                 audio_policy_forced_cfg_t config);
-        virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
-        virtual void setSystemProperty(const char* property, const char* value);
-        virtual status_t initCheck();
-        virtual audio_io_handle_t getOutput(audio_stream_type_t stream,
-                                            uint32_t samplingRate,
-                                            audio_format_t format,
-                                            audio_channel_mask_t channelMask,
-                                            audio_output_flags_t flags,
-                                            const audio_offload_info_t *offloadInfo);
-        virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
-                                            uint32_t samplingRate,
-                                            audio_format_t format,
-                                            audio_channel_mask_t channelMask,
-                                            audio_output_flags_t flags,
-                                            const audio_offload_info_t *offloadInfo);
-        virtual status_t startOutput(audio_io_handle_t output,
-                                     audio_stream_type_t stream,
-                                     int session = 0);
-        virtual status_t stopOutput(audio_io_handle_t output,
-                                    audio_stream_type_t stream,
-                                    int session = 0);
-        virtual void releaseOutput(audio_io_handle_t output);
-        virtual audio_io_handle_t getInput(audio_source_t inputSource,
-                                            uint32_t samplingRate,
-                                            audio_format_t format,
-                                            audio_channel_mask_t channelMask,
-                                            audio_session_t session,
-                                            audio_input_flags_t flags);
-
-        // indicates to the audio policy manager that the input starts being used.
-        virtual status_t startInput(audio_io_handle_t input,
-                                    audio_session_t session);
-
-        // indicates to the audio policy manager that the input stops being used.
-        virtual status_t stopInput(audio_io_handle_t input,
-                                   audio_session_t session);
-        virtual void releaseInput(audio_io_handle_t input,
-                                  audio_session_t session);
-        virtual void closeAllInputs();
-        virtual void initStreamVolume(audio_stream_type_t stream,
-                                                    int indexMin,
-                                                    int indexMax);
-        virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
-                                              int index,
-                                              audio_devices_t device);
-        virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
-                                              int *index,
-                                              audio_devices_t device);
-
-        // return the strategy corresponding to a given stream type
-        virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
-        // return the strategy corresponding to the given audio attributes
-        virtual uint32_t getStrategyForAttr(const audio_attributes_t *attr);
-
-        // return the enabled output devices for the given stream type
-        virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
-
-        virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc = NULL);
-        virtual status_t registerEffect(const effect_descriptor_t *desc,
-                                        audio_io_handle_t io,
-                                        uint32_t strategy,
-                                        int session,
-                                        int id);
-        virtual status_t unregisterEffect(int id);
-        virtual status_t setEffectEnabled(int id, bool enabled);
-
-        virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
-        // return whether a stream is playing remotely, override to change the definition of
-        //   local/remote playback, used for instance by notification manager to not make
-        //   media players lose audio focus when not playing locally
-        virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
-        virtual bool isSourceActive(audio_source_t source) const;
-
-        virtual status_t dump(int fd);
-
-        virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);
-
-        virtual status_t listAudioPorts(audio_port_role_t role,
-                                        audio_port_type_t type,
-                                        unsigned int *num_ports,
-                                        struct audio_port *ports,
-                                        unsigned int *generation);
-        virtual status_t getAudioPort(struct audio_port *port);
-        virtual status_t createAudioPatch(const struct audio_patch *patch,
-                                           audio_patch_handle_t *handle,
-                                           uid_t uid);
-        virtual status_t releaseAudioPatch(audio_patch_handle_t handle,
-                                              uid_t uid);
-        virtual status_t listAudioPatches(unsigned int *num_patches,
-                                          struct audio_patch *patches,
-                                          unsigned int *generation);
-        virtual status_t setAudioPortConfig(const struct audio_port_config *config);
-        virtual void clearAudioPatches(uid_t uid);
-
-        virtual status_t acquireSoundTriggerSession(audio_session_t *session,
-                                               audio_io_handle_t *ioHandle,
-                                               audio_devices_t *device);
-
-        virtual status_t releaseSoundTriggerSession(audio_session_t session);
-
-protected:
-
-        enum routing_strategy {
-            STRATEGY_MEDIA,
-            STRATEGY_PHONE,
-            STRATEGY_SONIFICATION,
-            STRATEGY_SONIFICATION_RESPECTFUL,
-            STRATEGY_DTMF,
-            STRATEGY_ENFORCED_AUDIBLE,
-            STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
-            NUM_STRATEGIES
-        };
-
-        // 4 points to define the volume attenuation curve, each characterized by the volume
-        // index (from 0 to 100) at which they apply, and the attenuation in dB at that index.
-        // we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl()
-
-        enum { VOLMIN = 0, VOLKNEE1 = 1, VOLKNEE2 = 2, VOLMAX = 3, VOLCNT = 4};
-
-        class VolumeCurvePoint
-        {
-        public:
-            int mIndex;
-            float mDBAttenuation;
-        };
-
-        // device categories used for volume curve management.
-        enum device_category {
-            DEVICE_CATEGORY_HEADSET,
-            DEVICE_CATEGORY_SPEAKER,
-            DEVICE_CATEGORY_EARPIECE,
-            DEVICE_CATEGORY_EXT_MEDIA,
-            DEVICE_CATEGORY_CNT
-        };
-
-        class HwModule;
-
-        class AudioGain: public RefBase
-        {
-        public:
-            AudioGain(int index, bool useInChannelMask);
-            virtual ~AudioGain() {}
-
-            void dump(int fd, int spaces, int index) const;
-
-            void getDefaultConfig(struct audio_gain_config *config);
-            status_t checkConfig(const struct audio_gain_config *config);
-            int               mIndex;
-            struct audio_gain mGain;
-            bool              mUseInChannelMask;
-        };
-
-        class AudioPort: public virtual RefBase
-        {
-        public:
-            AudioPort(const String8& name, audio_port_type_t type,
-                      audio_port_role_t role, const sp<HwModule>& module);
-            virtual ~AudioPort() {}
-
-            virtual void toAudioPort(struct audio_port *port) const;
-
-            void importAudioPort(const sp<AudioPort> port);
-            void clearCapabilities();
-
-            void loadSamplingRates(char *name);
-            void loadFormats(char *name);
-            void loadOutChannels(char *name);
-            void loadInChannels(char *name);
-
-            audio_gain_mode_t loadGainMode(char *name);
-            void loadGain(cnode *root, int index);
-            void loadGains(cnode *root);
-
-            // searches for an exact match
-            status_t checkExactSamplingRate(uint32_t samplingRate) const;
-            // searches for a compatible match, and returns the best match via updatedSamplingRate
-            status_t checkCompatibleSamplingRate(uint32_t samplingRate,
-                    uint32_t *updatedSamplingRate) const;
-            // searches for an exact match
-            status_t checkExactChannelMask(audio_channel_mask_t channelMask) const;
-            // searches for a compatible match, currently implemented for input channel masks only
-            status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask) const;
-            status_t checkFormat(audio_format_t format) const;
-            status_t checkGain(const struct audio_gain_config *gainConfig, int index) const;
-
-            uint32_t pickSamplingRate() const;
-            audio_channel_mask_t pickChannelMask() const;
-            audio_format_t pickFormat() const;
-
-            static const audio_format_t sPcmFormatCompareTable[];
-            static int compareFormats(audio_format_t format1, audio_format_t format2);
-
-            void dump(int fd, int spaces) const;
-
-            String8           mName;
-            audio_port_type_t mType;
-            audio_port_role_t mRole;
-            bool              mUseInChannelMask;
-            // by convention, "0' in the first entry in mSamplingRates, mChannelMasks or mFormats
-            // indicates the supported parameters should be read from the output stream
-            // after it is opened for the first time
-            Vector <uint32_t> mSamplingRates; // supported sampling rates
-            Vector <audio_channel_mask_t> mChannelMasks; // supported channel masks
-            Vector <audio_format_t> mFormats; // supported audio formats
-            Vector < sp<AudioGain> > mGains; // gain controllers
-            sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
-            uint32_t mFlags; // attribute flags (e.g primary output,
-                                                // direct output...).
-        };
-
-        class AudioPortConfig: public virtual RefBase
-        {
-        public:
-            AudioPortConfig();
-            virtual ~AudioPortConfig() {}
-
-            status_t applyAudioPortConfig(const struct audio_port_config *config,
-                                          struct audio_port_config *backupConfig = NULL);
-            virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
-                                   const struct audio_port_config *srcConfig = NULL) const = 0;
-            virtual sp<AudioPort> getAudioPort() const = 0;
-            uint32_t mSamplingRate;
-            audio_format_t mFormat;
-            audio_channel_mask_t mChannelMask;
-            struct audio_gain_config mGain;
-        };
-
-
-        class AudioPatch: public RefBase
-        {
-        public:
-            AudioPatch(audio_patch_handle_t handle,
-                       const struct audio_patch *patch, uid_t uid) :
-                           mHandle(handle), mPatch(*patch), mUid(uid), mAfPatchHandle(0) {}
-
-            status_t dump(int fd, int spaces, int index) const;
-
-            audio_patch_handle_t mHandle;
-            struct audio_patch mPatch;
-            uid_t mUid;
-            audio_patch_handle_t mAfPatchHandle;
-        };
-
-        class DeviceDescriptor: public AudioPort, public AudioPortConfig
-        {
-        public:
-            DeviceDescriptor(const String8& name, audio_devices_t type);
-
-            virtual ~DeviceDescriptor() {}
-
-            bool equals(const sp<DeviceDescriptor>& other) const;
-            virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
-                                   const struct audio_port_config *srcConfig = NULL) const;
-            virtual sp<AudioPort> getAudioPort() const { return (AudioPort*) this; }
-
-            virtual void toAudioPort(struct audio_port *port) const;
-
-            status_t dump(int fd, int spaces, int index) const;
-
-            audio_devices_t mDeviceType;
-            String8 mAddress;
-            audio_port_handle_t mId;
-        };
-
-        class DeviceVector : public SortedVector< sp<DeviceDescriptor> >
-        {
-        public:
-            DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
-
-            ssize_t         add(const sp<DeviceDescriptor>& item);
-            ssize_t         remove(const sp<DeviceDescriptor>& item);
-            ssize_t         indexOf(const sp<DeviceDescriptor>& item) const;
-
-            audio_devices_t types() const { return mDeviceTypes; }
-
-            void loadDevicesFromType(audio_devices_t types);
-            void loadDevicesFromName(char *name, const DeviceVector& declaredDevices);
-
-            sp<DeviceDescriptor> getDevice(audio_devices_t type, String8 address) const;
-            DeviceVector getDevicesFromType(audio_devices_t types) const;
-            sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
-            sp<DeviceDescriptor> getDeviceFromName(const String8& name) const;
-            DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address)
-                    const;
-
-        private:
-            void refreshTypes();
-            audio_devices_t mDeviceTypes;
-        };
-
-        // the IOProfile class describes the capabilities of an output or input stream.
-        // It is currently assumed that all combination of listed parameters are supported.
-        // It is used by the policy manager to determine if an output or input is suitable for
-        // a given use case,  open/close it accordingly and connect/disconnect audio tracks
-        // to/from it.
-        class IOProfile : public AudioPort
-        {
-        public:
-            IOProfile(const String8& name, audio_port_role_t role, const sp<HwModule>& module);
-            virtual ~IOProfile();
-
-            // This method is used for both output and input.
-            // If parameter updatedSamplingRate is non-NULL, it is assigned the actual sample rate.
-            // For input, flags is interpreted as audio_input_flags_t.
-            // TODO: merge audio_output_flags_t and audio_input_flags_t.
-            bool isCompatibleProfile(audio_devices_t device,
-                                     uint32_t samplingRate,
-                                     uint32_t *updatedSamplingRate,
-                                     audio_format_t format,
-                                     audio_channel_mask_t channelMask,
-                                     uint32_t flags) const;
-
-            void dump(int fd);
-            void log();
-
-            DeviceVector  mSupportedDevices; // supported devices
-                                             // (devices this output can be routed to)
-        };
-
-        class HwModule : public RefBase
-        {
-        public:
-                    HwModule(const char *name);
-                    ~HwModule();
-
-            status_t loadOutput(cnode *root);
-            status_t loadInput(cnode *root);
-            status_t loadDevice(cnode *root);
-
-            void dump(int fd);
-
-            const char *const        mName; // base name of the audio HW module (primary, a2dp ...)
-            uint32_t                 mHalVersion; // audio HAL API version
-            audio_module_handle_t    mHandle;
-            Vector < sp<IOProfile> > mOutputProfiles; // output profiles exposed by this module
-            Vector < sp<IOProfile> > mInputProfiles;  // input profiles exposed by this module
-            DeviceVector             mDeclaredDevices; // devices declared in audio_policy.conf
-
-        };
-
-        // default volume curve
-        static const VolumeCurvePoint sDefaultVolumeCurve[AudioPolicyManager::VOLCNT];
-        // default volume curve for media strategy
-        static const VolumeCurvePoint sDefaultMediaVolumeCurve[AudioPolicyManager::VOLCNT];
-        // volume curve for non-media audio on ext media outputs (HDMI, Line, etc)
-        static const VolumeCurvePoint sExtMediaSystemVolumeCurve[AudioPolicyManager::VOLCNT];
-        // volume curve for media strategy on speakers
-        static const VolumeCurvePoint sSpeakerMediaVolumeCurve[AudioPolicyManager::VOLCNT];
-        static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[AudioPolicyManager::VOLCNT];
-        // volume curve for sonification strategy on speakers
-        static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[AudioPolicyManager::VOLCNT];
-        static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[AudioPolicyManager::VOLCNT];
-        static const VolumeCurvePoint sDefaultSystemVolumeCurve[AudioPolicyManager::VOLCNT];
-        static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[AudioPolicyManager::VOLCNT];
-        static const VolumeCurvePoint sHeadsetSystemVolumeCurve[AudioPolicyManager::VOLCNT];
-        static const VolumeCurvePoint sDefaultVoiceVolumeCurve[AudioPolicyManager::VOLCNT];
-        static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[AudioPolicyManager::VOLCNT];
-        static const VolumeCurvePoint sLinearVolumeCurve[AudioPolicyManager::VOLCNT];
-        static const VolumeCurvePoint sSilentVolumeCurve[AudioPolicyManager::VOLCNT];
-        // default volume curves per stream and device category. See initializeVolumeCurves()
-        static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][DEVICE_CATEGORY_CNT];
-
-        // descriptor for audio outputs. Used to maintain current configuration of each opened audio output
-        // and keep track of the usage of this output by each audio stream type.
-        class AudioOutputDescriptor: public AudioPortConfig
-        {
-        public:
-            AudioOutputDescriptor(const sp<IOProfile>& profile);
-
-            status_t    dump(int fd);
-
-            audio_devices_t device() const;
-            void changeRefCount(audio_stream_type_t stream, int delta);
-
-            bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
-            audio_devices_t supportedDevices();
-            uint32_t latency();
-            bool sharesHwModuleWith(const sp<AudioOutputDescriptor> outputDesc);
-            bool isActive(uint32_t inPastMs = 0) const;
-            bool isStreamActive(audio_stream_type_t stream,
-                                uint32_t inPastMs = 0,
-                                nsecs_t sysTime = 0) const;
-            bool isStrategyActive(routing_strategy strategy,
-                             uint32_t inPastMs = 0,
-                             nsecs_t sysTime = 0) const;
-
-            virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
-                                   const struct audio_port_config *srcConfig = NULL) const;
-            virtual sp<AudioPort> getAudioPort() const { return mProfile; }
-            void toAudioPort(struct audio_port *port) const;
-
-            audio_port_handle_t mId;
-            audio_io_handle_t mIoHandle;              // output handle
-            uint32_t mLatency;                  //
-            audio_output_flags_t mFlags;   //
-            audio_devices_t mDevice;                   // current device this output is routed to
-            audio_patch_handle_t mPatchHandle;
-            uint32_t mRefCount[AUDIO_STREAM_CNT]; // number of streams of each type using this output
-            nsecs_t mStopTime[AUDIO_STREAM_CNT];
-            sp<AudioOutputDescriptor> mOutput1;    // used by duplicated outputs: first output
-            sp<AudioOutputDescriptor> mOutput2;    // used by duplicated outputs: second output
-            float mCurVolume[AUDIO_STREAM_CNT];   // current stream volume
-            int mMuteCount[AUDIO_STREAM_CNT];     // mute request counter
-            const sp<IOProfile> mProfile;          // I/O profile this output derives from
-            bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible
-                                                // device selection. See checkDeviceMuteStrategies()
-            uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only)
-        };
-
-        // descriptor for audio inputs. Used to maintain current configuration of each opened audio input
-        // and keep track of the usage of this input.
-        class AudioInputDescriptor: public AudioPortConfig
-        {
-        public:
-            AudioInputDescriptor(const sp<IOProfile>& profile);
-
-            status_t    dump(int fd);
-
-            audio_port_handle_t           mId;
-            audio_io_handle_t             mIoHandle;       // input handle
-            audio_devices_t               mDevice;         // current device this input is routed to
-            audio_patch_handle_t          mPatchHandle;
-            uint32_t                      mRefCount;       // number of AudioRecord clients using
-                                                           // this input
-            uint32_t                      mOpenRefCount;
-            audio_source_t                mInputSource;    // input source selected by application
-                                                           //(mediarecorder.h)
-            const sp<IOProfile>           mProfile;        // I/O profile this output derives from
-            SortedVector<audio_session_t> mSessions;       // audio sessions attached to this input
-            bool                          mIsSoundTrigger; // used by a soundtrigger capture
-
-            virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
-                                   const struct audio_port_config *srcConfig = NULL) const;
-            virtual sp<AudioPort> getAudioPort() const { return mProfile; }
-            void toAudioPort(struct audio_port *port) const;
-        };
-
-        // stream descriptor used for volume control
-        class StreamDescriptor
-        {
-        public:
-            StreamDescriptor();
-
-            int getVolumeIndex(audio_devices_t device);
-            void dump(int fd);
-
-            int mIndexMin;      // min volume index
-            int mIndexMax;      // max volume index
-            KeyedVector<audio_devices_t, int> mIndexCur;   // current volume index per device
-            bool mCanBeMuted;   // true is the stream can be muted
-
-            const VolumeCurvePoint *mVolumeCurve[DEVICE_CATEGORY_CNT];
-        };
-
-        // stream descriptor used for volume control
-        class EffectDescriptor : public RefBase
-        {
-        public:
-
-            status_t dump(int fd);
-
-            int mIo;                // io the effect is attached to
-            routing_strategy mStrategy; // routing strategy the effect is associated to
-            int mSession;               // audio session the effect is on
-            effect_descriptor_t mDesc;  // effect descriptor
-            bool mEnabled;              // enabled state: CPU load being used or not
-        };
-
-        void addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc);
-        void addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc);
-
-        // return the strategy corresponding to a given stream type
-        static routing_strategy getStrategy(audio_stream_type_t stream);
-
-        // return appropriate device for streams handled by the specified strategy according to current
-        // phone state, connected devices...
-        // if fromCache is true, the device is returned from mDeviceForStrategy[],
-        // otherwise it is determine by current state
-        // (device connected,phone state, force use, a2dp output...)
-        // This allows to:
-        //  1 speed up process when the state is stable (when starting or stopping an output)
-        //  2 access to either current device selection (fromCache == true) or
-        // "future" device selection (fromCache == false) when called from a context
-        //  where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND
-        //  before updateDevicesAndOutputs() is called.
-        virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy,
-                                                     bool fromCache);
-
-        // change the route of the specified output. Returns the number of ms we have slept to
-        // allow new routing to take effect in certain cases.
-        uint32_t setOutputDevice(audio_io_handle_t output,
-                             audio_devices_t device,
-                             bool force = false,
-                             int delayMs = 0,
-                             audio_patch_handle_t *patchHandle = NULL,
-                             const char* address = NULL);
-        status_t resetOutputDevice(audio_io_handle_t output,
-                                   int delayMs = 0,
-                                   audio_patch_handle_t *patchHandle = NULL);
-        status_t setInputDevice(audio_io_handle_t input,
-                                audio_devices_t device,
-                                bool force = false,
-                                audio_patch_handle_t *patchHandle = NULL);
-        status_t resetInputDevice(audio_io_handle_t input,
-                                  audio_patch_handle_t *patchHandle = NULL);
-
-        // select input device corresponding to requested audio source
-        virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource);
-
-        // return io handle of active input or 0 if no input is active
-        //    Only considers inputs from physical devices (e.g. main mic, headset mic) when
-        //    ignoreVirtualInputs is true.
-        audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
-
-        uint32_t activeInputsCount() const;
-
-        // initialize volume curves for each strategy and device category
-        void initializeVolumeCurves();
-
-        // compute the actual volume for a given stream according to the requested index and a particular
-        // device
-        virtual float computeVolume(audio_stream_type_t stream, int index,
-                                    audio_io_handle_t output, audio_devices_t device);
-
-        // check that volume change is permitted, compute and send new volume to audio hardware
-        virtual status_t checkAndSetVolume(audio_stream_type_t stream, int index,
-                                           audio_io_handle_t output,
-                                           audio_devices_t device,
-                                           int delayMs = 0, bool force = false);
-
-        // apply all stream volumes to the specified output and device
-        void applyStreamVolumes(audio_io_handle_t output, audio_devices_t device, int delayMs = 0, bool force = false);
-
-        // Mute or unmute all streams handled by the specified strategy on the specified output
-        void setStrategyMute(routing_strategy strategy,
-                             bool on,
-                             audio_io_handle_t output,
-                             int delayMs = 0,
-                             audio_devices_t device = (audio_devices_t)0);
-
-        // Mute or unmute the stream on the specified output
-        void setStreamMute(audio_stream_type_t stream,
-                           bool on,
-                           audio_io_handle_t output,
-                           int delayMs = 0,
-                           audio_devices_t device = (audio_devices_t)0);
-
-        // handle special cases for sonification strategy while in call: mute streams or replace by
-        // a special tone in the device used for communication
-        void handleIncallSonification(audio_stream_type_t stream, bool starting, bool stateChange);
-
-        // true if device is in a telephony or VoIP call
-        virtual bool isInCall();
-
-        // true if given state represents a device in a telephony or VoIP call
-        virtual bool isStateInCall(int state);
-
-        // when a device is connected, checks if an open output can be routed
-        // to this device. If none is open, tries to open one of the available outputs.
-        // Returns an output suitable to this device or 0.
-        // when a device is disconnected, checks if an output is not used any more and
-        // returns its handle if any.
-        // transfers the audio tracks and effects from one output thread to another accordingly.
-        status_t checkOutputsForDevice(const sp<DeviceDescriptor> devDesc,
-                                       audio_policy_dev_state_t state,
-                                       SortedVector<audio_io_handle_t>& outputs,
-                                       const String8 address);
-
-        status_t checkInputsForDevice(audio_devices_t device,
-                                      audio_policy_dev_state_t state,
-                                      SortedVector<audio_io_handle_t>& inputs,
-                                      const String8 address);
-
-        // close an output and its companion duplicating output.
-        void closeOutput(audio_io_handle_t output);
-
-        // close an input.
-        void closeInput(audio_io_handle_t input);
-
-        // checks and if necessary changes outputs used for all strategies.
-        // must be called every time a condition that affects the output choice for a given strategy
-        // changes: connected device, phone state, force use...
-        // Must be called before updateDevicesAndOutputs()
-        void checkOutputForStrategy(routing_strategy strategy);
-
-        // Same as checkOutputForStrategy() but for a all strategies in order of priority
-        void checkOutputForAllStrategies();
-
-        // manages A2DP output suspend/restore according to phone state and BT SCO usage
-        void checkA2dpSuspend();
-
-        // returns the A2DP output handle if it is open or 0 otherwise
-        audio_io_handle_t getA2dpOutput();
-
-        // selects the most appropriate device on output for current state
-        // must be called every time a condition that affects the device choice for a given output is
-        // changed: connected device, phone state, force use, output start, output stop..
-        // see getDeviceForStrategy() for the use of fromCache parameter
-        audio_devices_t getNewOutputDevice(audio_io_handle_t output, bool fromCache);
-
-        // updates cache of device used by all strategies (mDeviceForStrategy[])
-        // must be called every time a condition that affects the device choice for a given strategy is
-        // changed: connected device, phone state, force use...
-        // cached values are used by getDeviceForStrategy() if parameter fromCache is true.
-         // Must be called after checkOutputForAllStrategies()
-        void updateDevicesAndOutputs();
-
-        // selects the most appropriate device on input for current state
-        audio_devices_t getNewInputDevice(audio_io_handle_t input);
-
-        virtual uint32_t getMaxEffectsCpuLoad();
-        virtual uint32_t getMaxEffectsMemory();
-#ifdef AUDIO_POLICY_TEST
-        virtual     bool        threadLoop();
-                    void        exit();
-        int testOutputIndex(audio_io_handle_t output);
-#endif //AUDIO_POLICY_TEST
-
-        status_t setEffectEnabled(const sp<EffectDescriptor>& effectDesc, bool enabled);
-
-        // returns the category the device belongs to with regard to volume curve management
-        static device_category getDeviceCategory(audio_devices_t device);
-
-        // extract one device relevant for volume control from multiple device selection
-        static audio_devices_t getDeviceForVolume(audio_devices_t device);
-
-        SortedVector<audio_io_handle_t> getOutputsForDevice(audio_devices_t device,
-                        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs);
-        bool vectorsEqual(SortedVector<audio_io_handle_t>& outputs1,
-                                           SortedVector<audio_io_handle_t>& outputs2);
-
-        // mute/unmute strategies using an incompatible device combination
-        // if muting, wait for the audio in pcm buffer to be drained before proceeding
-        // if unmuting, unmute only after the specified delay
-        // Returns the number of ms waited
-        uint32_t  checkDeviceMuteStrategies(sp<AudioOutputDescriptor> outputDesc,
-                                            audio_devices_t prevDevice,
-                                            uint32_t delayMs);
-
-        audio_io_handle_t selectOutput(const SortedVector<audio_io_handle_t>& outputs,
-                                       audio_output_flags_t flags,
-                                       audio_format_t format);
-        // samplingRate parameter is an in/out and so may be modified
-        sp<IOProfile> getInputProfile(audio_devices_t device,
-                                   uint32_t& samplingRate,
-                                   audio_format_t format,
-                                   audio_channel_mask_t channelMask,
-                                   audio_input_flags_t flags);
-        sp<IOProfile> getProfileForDirectOutput(audio_devices_t device,
-                                                       uint32_t samplingRate,
-                                                       audio_format_t format,
-                                                       audio_channel_mask_t channelMask,
-                                                       audio_output_flags_t flags);
-
-        audio_io_handle_t selectOutputForEffects(const SortedVector<audio_io_handle_t>& outputs);
-
-        bool isNonOffloadableEffectEnabled();
-
-        status_t addAudioPatch(audio_patch_handle_t handle,
-                               const sp<AudioPatch>& patch);
-        status_t removeAudioPatch(audio_patch_handle_t handle);
-
-        sp<AudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const;
-        sp<AudioInputDescriptor> getInputFromId(audio_port_handle_t id) const;
-        sp<HwModule> getModuleForDevice(audio_devices_t device) const;
-        sp<HwModule> getModuleFromName(const char *name) const;
-        audio_devices_t availablePrimaryOutputDevices();
-        audio_devices_t availablePrimaryInputDevices();
-
-        void updateCallRouting(audio_devices_t rxDevice, int delayMs = 0);
-
-        //
-        // Audio policy configuration file parsing (audio_policy.conf)
-        //
-        static uint32_t stringToEnum(const struct StringToEnum *table,
-                                     size_t size,
-                                     const char *name);
-        static const char *enumToString(const struct StringToEnum *table,
-                                      size_t size,
-                                      uint32_t value);
-        static bool stringToBool(const char *value);
-        static uint32_t parseOutputFlagNames(char *name);
-        static uint32_t parseInputFlagNames(char *name);
-        static audio_devices_t parseDeviceNames(char *name);
-        void loadHwModule(cnode *root);
-        void loadHwModules(cnode *root);
-        void loadGlobalConfig(cnode *root, const sp<HwModule>& module);
-        status_t loadAudioPolicyConfig(const char *path);
-        void defaultAudioPolicyConfig(void);
-
-
-        uid_t mUidCached;
-        AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
-        audio_io_handle_t mPrimaryOutput;              // primary output handle
-        // list of descriptors for outputs currently opened
-        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > mOutputs;
-        // copy of mOutputs before setDeviceConnectionState() opens new outputs
-        // reset to mOutputs when updateDevicesAndOutputs() is called.
-        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > mPreviousOutputs;
-        DefaultKeyedVector<audio_io_handle_t, sp<AudioInputDescriptor> > mInputs;     // list of input descriptors
-        DeviceVector  mAvailableOutputDevices; // all available output devices
-        DeviceVector  mAvailableInputDevices;  // all available input devices
-        int mPhoneState;                                                    // current phone state
-        audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT];   // current forced use configuration
-
-        StreamDescriptor mStreams[AUDIO_STREAM_CNT];           // stream descriptors for volume control
-        bool    mLimitRingtoneVolume;                                       // limit ringtone volume to music volume if headset connected
-        audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
-        float   mLastVoiceVolume;                                           // last voice volume value sent to audio HAL
-
-        // Maximum CPU load allocated to audio effects in 0.1 MIPS (ARMv5TE, 0 WS memory) units
-        static const uint32_t MAX_EFFECTS_CPU_LOAD = 1000;
-        // Maximum memory allocated to audio effects in KB
-        static const uint32_t MAX_EFFECTS_MEMORY = 512;
-        uint32_t mTotalEffectsCpuLoad; // current CPU load used by effects
-        uint32_t mTotalEffectsMemory;  // current memory used by effects
-        KeyedVector<int, sp<EffectDescriptor> > mEffects;  // list of registered audio effects
-        bool    mA2dpSuspended;  // true if A2DP output is suspended
-        sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
-        bool mSpeakerDrcEnabled;// true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER path
-                                // to boost soft sounds, used to adjust volume curves accordingly
-
-        Vector < sp<HwModule> > mHwModules;
-        volatile int32_t mNextUniqueId;
-        volatile int32_t mAudioPortGeneration;
-
-        DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> > mAudioPatches;
-
-        DefaultKeyedVector<audio_session_t, audio_io_handle_t> mSoundTriggerSessions;
-
-        sp<AudioPatch> mCallTxPatch;
-        sp<AudioPatch> mCallRxPatch;
-
-        // for supporting "beacon" streams, i.e. streams that only play on speaker, and never
-        // when something other than STREAM_TTS (a.k.a. "Transmitted Through Speaker") is playing
-        enum {
-            STARTING_OUTPUT,
-            STARTING_BEACON,
-            STOPPING_OUTPUT,
-            STOPPING_BEACON
-        };
-        uint32_t mBeaconMuteRefCount;   // ref count for stream that would mute beacon
-        uint32_t mBeaconPlayingRefCount;// ref count for the playing beacon streams
-        bool mBeaconMuted;              // has STREAM_TTS been muted
-
-#ifdef AUDIO_POLICY_TEST
-        Mutex   mLock;
-        Condition mWaitWorkCV;
-
-        int             mCurOutput;
-        bool            mDirectOutput;
-        audio_io_handle_t mTestOutputs[NUM_TEST_OUTPUTS];
-        int             mTestInput;
-        uint32_t        mTestDevice;
-        uint32_t        mTestSamplingRate;
-        uint32_t        mTestFormat;
-        uint32_t        mTestChannels;
-        uint32_t        mTestLatencyMs;
-#endif //AUDIO_POLICY_TEST
-        static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
-                int indexInUi);
-private:
-        // updates device caching and output for streams that can influence the
-        //    routing of notifications
-        void handleNotificationRoutingForStream(audio_stream_type_t stream);
-        static bool isVirtualInputDevice(audio_devices_t device);
-        static bool deviceDistinguishesOnAddress(audio_devices_t device);
-        // find the outputs on a given output descriptor that have the given address.
-        // to be called on an AudioOutputDescriptor whose supported devices (as defined
-        //   in mProfile->mSupportedDevices) matches the device whose address is to be matched.
-        // see deviceDistinguishesOnAddress(audio_devices_t) for whether the device type is one
-        //   where addresses are used to distinguish between one connected device and another.
-        void findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/,
-                const String8 address /*in*/,
-                SortedVector<audio_io_handle_t>& outputs /*out*/);
-        uint32_t nextUniqueId();
-        uint32_t nextAudioPortGeneration();
-        uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; }
-        // internal method to return the output handle for the given device and format
-        audio_io_handle_t getOutputForDevice(
-                audio_devices_t device,
-                audio_stream_type_t stream,
-                uint32_t samplingRate,
-                audio_format_t format,
-                audio_channel_mask_t channelMask,
-                audio_output_flags_t flags,
-                const audio_offload_info_t *offloadInfo);
-        // internal function to derive a stream type value from audio attributes
-        audio_stream_type_t streamTypefromAttributesInt(const audio_attributes_t *attr);
-        // return true if any output is playing anything besides the stream to ignore
-        bool isAnyOutputActive(audio_stream_type_t streamToIgnore);
-        // event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON
-        // returns 0 if no mute/unmute event happened, the largest latency of the device where
-        //   the mute/unmute happened
-        uint32_t handleEventForBeacon(int event);
-        uint32_t setBeaconMute(bool mute);
-};
-
-};
diff --git a/services/audiopolicy/AudioPolicyFactory.cpp b/services/audiopolicy/manager/AudioPolicyFactory.cpp
similarity index 94%
rename from services/audiopolicy/AudioPolicyFactory.cpp
rename to services/audiopolicy/manager/AudioPolicyFactory.cpp
index 2ae7bc1..9910a1f 100644
--- a/services/audiopolicy/AudioPolicyFactory.cpp
+++ b/services/audiopolicy/manager/AudioPolicyFactory.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "AudioPolicyManager.h"
+#include "managerdefault/AudioPolicyManager.h"
 
 namespace android {
 
diff --git a/services/audiopolicy/AudioPolicyFactory.cpp b/services/audiopolicy/managerdefault/ApmImplDefinitions.h
similarity index 60%
copy from services/audiopolicy/AudioPolicyFactory.cpp
copy to services/audiopolicy/managerdefault/ApmImplDefinitions.h
index 2ae7bc1..620979b 100644
--- a/services/audiopolicy/AudioPolicyFactory.cpp
+++ b/services/audiopolicy/managerdefault/ApmImplDefinitions.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-#include "AudioPolicyManager.h"
-
 namespace android {
 
-extern "C" AudioPolicyInterface* createAudioPolicyManager(
-        AudioPolicyClientInterface *clientInterface)
-{
-    return new AudioPolicyManager(clientInterface);
-}
+enum routing_strategy {
+    STRATEGY_MEDIA,
+    STRATEGY_PHONE,
+    STRATEGY_SONIFICATION,
+    STRATEGY_SONIFICATION_RESPECTFUL,
+    STRATEGY_DTMF,
+    STRATEGY_ENFORCED_AUDIBLE,
+    STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
+    STRATEGY_ACCESSIBILITY,
+    STRATEGY_REROUTING,
+    NUM_STRATEGIES
+};
 
-extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
-{
-    delete interface;
-}
-
-}; // namespace android
+}; //namespace android
diff --git a/services/audiopolicy/managerdefault/AudioInputDescriptor.cpp b/services/audiopolicy/managerdefault/AudioInputDescriptor.cpp
new file mode 100644
index 0000000..f4054c8
--- /dev/null
+++ b/services/audiopolicy/managerdefault/AudioInputDescriptor.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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 "APM::AudioInputDescriptor"
+//#define LOG_NDEBUG 0
+
+#include "AudioPolicyManager.h"
+
+namespace android {
+
+AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile)
+    : mId(0), mIoHandle(0),
+      mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), mPatchHandle(0), mRefCount(0),
+      mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile), mIsSoundTrigger(false)
+{
+    if (profile != NULL) {
+        mSamplingRate = profile->pickSamplingRate();
+        mFormat = profile->pickFormat();
+        mChannelMask = profile->pickChannelMask();
+        if (profile->mGains.size() > 0) {
+            profile->mGains[0]->getDefaultConfig(&mGain);
+        }
+    }
+}
+
+void AudioInputDescriptor::toAudioPortConfig(
+                                                   struct audio_port_config *dstConfig,
+                                                   const struct audio_port_config *srcConfig) const
+{
+    ALOG_ASSERT(mProfile != 0,
+                "toAudioPortConfig() called on input with null profile %d", mIoHandle);
+    dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
+                            AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
+    if (srcConfig != NULL) {
+        dstConfig->config_mask |= srcConfig->config_mask;
+    }
+
+    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
+
+    dstConfig->id = mId;
+    dstConfig->role = AUDIO_PORT_ROLE_SINK;
+    dstConfig->type = AUDIO_PORT_TYPE_MIX;
+    dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle;
+    dstConfig->ext.mix.handle = mIoHandle;
+    dstConfig->ext.mix.usecase.source = mInputSource;
+}
+
+void AudioInputDescriptor::toAudioPort(
+                                                    struct audio_port *port) const
+{
+    ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle);
+
+    mProfile->toAudioPort(port);
+    port->id = mId;
+    toAudioPortConfig(&port->active_config);
+    port->ext.mix.hw_module = mProfile->mModule->mHandle;
+    port->ext.mix.handle = mIoHandle;
+    port->ext.mix.latency_class = AUDIO_LATENCY_NORMAL;
+}
+
+status_t AudioInputDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " ID: %d\n", mId);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Open Ref Count %d\n", mOpenRefCount);
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
+}; //namespace android
diff --git a/services/audiopolicy/managerdefault/AudioInputDescriptor.h b/services/audiopolicy/managerdefault/AudioInputDescriptor.h
new file mode 100644
index 0000000..02579e6
--- /dev/null
+++ b/services/audiopolicy/managerdefault/AudioInputDescriptor.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.
+ */
+
+namespace android {
+
+// descriptor for audio inputs. Used to maintain current configuration of each opened audio input
+// and keep track of the usage of this input.
+class AudioInputDescriptor: public AudioPortConfig
+{
+public:
+    AudioInputDescriptor(const sp<IOProfile>& profile);
+
+    status_t    dump(int fd);
+
+    audio_port_handle_t           mId;
+    audio_io_handle_t             mIoHandle;       // input handle
+    audio_devices_t               mDevice;         // current device this input is routed to
+    AudioMix                      *mPolicyMix;     // non NULL when used by a dynamic policy
+    audio_patch_handle_t          mPatchHandle;
+    uint32_t                      mRefCount;       // number of AudioRecord clients using
+    // this input
+    uint32_t                      mOpenRefCount;
+    audio_source_t                mInputSource;    // input source selected by application
+    //(mediarecorder.h)
+    const sp<IOProfile>           mProfile;        // I/O profile this output derives from
+    SortedVector<audio_session_t> mSessions;       // audio sessions attached to this input
+    bool                          mIsSoundTrigger; // used by a soundtrigger capture
+
+    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
+            const struct audio_port_config *srcConfig = NULL) const;
+    virtual sp<AudioPort> getAudioPort() const { return mProfile; }
+    void toAudioPort(struct audio_port *port) const;
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp b/services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp
new file mode 100644
index 0000000..4b85972
--- /dev/null
+++ b/services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp
@@ -0,0 +1,221 @@
+/*
+ * 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 "APM::AudioOutputDescriptor"
+//#define LOG_NDEBUG 0
+
+#include "AudioPolicyManager.h"
+
+namespace android {
+
+AudioOutputDescriptor::AudioOutputDescriptor(
+        const sp<IOProfile>& profile)
+    : mId(0), mIoHandle(0), mLatency(0),
+    mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
+    mPatchHandle(0),
+    mOutput1(0), mOutput2(0), mProfile(profile), mDirectOpenCount(0)
+{
+    // clear usage count for all stream types
+    for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
+        mRefCount[i] = 0;
+        mCurVolume[i] = -1.0;
+        mMuteCount[i] = 0;
+        mStopTime[i] = 0;
+    }
+    for (int i = 0; i < NUM_STRATEGIES; i++) {
+        mStrategyMutedByDevice[i] = false;
+    }
+    if (profile != NULL) {
+        mFlags = (audio_output_flags_t)profile->mFlags;
+        mSamplingRate = profile->pickSamplingRate();
+        mFormat = profile->pickFormat();
+        mChannelMask = profile->pickChannelMask();
+        if (profile->mGains.size() > 0) {
+            profile->mGains[0]->getDefaultConfig(&mGain);
+        }
+    }
+}
+
+audio_devices_t AudioOutputDescriptor::device() const
+{
+    if (isDuplicated()) {
+        return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice);
+    } else {
+        return mDevice;
+    }
+}
+
+uint32_t AudioOutputDescriptor::latency()
+{
+    if (isDuplicated()) {
+        return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency;
+    } else {
+        return mLatency;
+    }
+}
+
+bool AudioOutputDescriptor::sharesHwModuleWith(
+        const sp<AudioOutputDescriptor> outputDesc)
+{
+    if (isDuplicated()) {
+        return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc);
+    } else if (outputDesc->isDuplicated()){
+        return sharesHwModuleWith(outputDesc->mOutput1) || sharesHwModuleWith(outputDesc->mOutput2);
+    } else {
+        return (mProfile->mModule == outputDesc->mProfile->mModule);
+    }
+}
+
+void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream,
+                                                                   int delta)
+{
+    // forward usage count change to attached outputs
+    if (isDuplicated()) {
+        mOutput1->changeRefCount(stream, delta);
+        mOutput2->changeRefCount(stream, delta);
+    }
+    if ((delta + (int)mRefCount[stream]) < 0) {
+        ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d",
+              delta, stream, mRefCount[stream]);
+        mRefCount[stream] = 0;
+        return;
+    }
+    mRefCount[stream] += delta;
+    ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
+}
+
+audio_devices_t AudioOutputDescriptor::supportedDevices()
+{
+    if (isDuplicated()) {
+        return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices());
+    } else {
+        return mProfile->mSupportedDevices.types() ;
+    }
+}
+
+bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const
+{
+    return isStrategyActive(NUM_STRATEGIES, inPastMs);
+}
+
+bool AudioOutputDescriptor::isStrategyActive(routing_strategy strategy,
+                                                                       uint32_t inPastMs,
+                                                                       nsecs_t sysTime) const
+{
+    if ((sysTime == 0) && (inPastMs != 0)) {
+        sysTime = systemTime();
+    }
+    for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
+        if (i == AUDIO_STREAM_PATCH) {
+            continue;
+        }
+        if (((AudioPolicyManager::getStrategy((audio_stream_type_t)i) == strategy) ||
+                (NUM_STRATEGIES == strategy)) &&
+                isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream,
+                                                                       uint32_t inPastMs,
+                                                                       nsecs_t sysTime) const
+{
+    if (mRefCount[stream] != 0) {
+        return true;
+    }
+    if (inPastMs == 0) {
+        return false;
+    }
+    if (sysTime == 0) {
+        sysTime = systemTime();
+    }
+    if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) {
+        return true;
+    }
+    return false;
+}
+
+void AudioOutputDescriptor::toAudioPortConfig(
+                                                 struct audio_port_config *dstConfig,
+                                                 const struct audio_port_config *srcConfig) const
+{
+    ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle);
+
+    dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
+                            AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
+    if (srcConfig != NULL) {
+        dstConfig->config_mask |= srcConfig->config_mask;
+    }
+    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
+
+    dstConfig->id = mId;
+    dstConfig->role = AUDIO_PORT_ROLE_SOURCE;
+    dstConfig->type = AUDIO_PORT_TYPE_MIX;
+    dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle;
+    dstConfig->ext.mix.handle = mIoHandle;
+    dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT;
+}
+
+void AudioOutputDescriptor::toAudioPort(
+                                                    struct audio_port *port) const
+{
+    ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle);
+    mProfile->toAudioPort(port);
+    port->id = mId;
+    toAudioPortConfig(&port->active_config);
+    port->ext.mix.hw_module = mProfile->mModule->mHandle;
+    port->ext.mix.handle = mIoHandle;
+    port->ext.mix.latency_class =
+            mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL;
+}
+
+status_t AudioOutputDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " ID: %d\n", mId);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Format: %08x\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Devices %08x\n", device());
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Stream volume refCount muteCount\n");
+    result.append(buffer);
+    for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
+        snprintf(buffer, SIZE, " %02d     %.03f     %02d       %02d\n",
+                 i, mCurVolume[i], mRefCount[i], mMuteCount[i]);
+        result.append(buffer);
+    }
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
+
+
+}; //namespace android
diff --git a/services/audiopolicy/managerdefault/AudioOutputDescriptor.h b/services/audiopolicy/managerdefault/AudioOutputDescriptor.h
new file mode 100644
index 0000000..32f46e4
--- /dev/null
+++ b/services/audiopolicy/managerdefault/AudioOutputDescriptor.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#include "ApmImplDefinitions.h"
+
+namespace android {
+
+// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
+// and keep track of the usage of this output by each audio stream type.
+class AudioOutputDescriptor: public AudioPortConfig
+{
+public:
+    AudioOutputDescriptor(const sp<IOProfile>& profile);
+
+    status_t    dump(int fd);
+
+    audio_devices_t device() const;
+    void changeRefCount(audio_stream_type_t stream, int delta);
+
+    bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
+    audio_devices_t supportedDevices();
+    uint32_t latency();
+    bool sharesHwModuleWith(const sp<AudioOutputDescriptor> outputDesc);
+    bool isActive(uint32_t inPastMs = 0) const;
+    bool isStreamActive(audio_stream_type_t stream,
+                        uint32_t inPastMs = 0,
+                        nsecs_t sysTime = 0) const;
+    bool isStrategyActive(routing_strategy strategy,
+                     uint32_t inPastMs = 0,
+                     nsecs_t sysTime = 0) const;
+
+    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
+                           const struct audio_port_config *srcConfig = NULL) const;
+    virtual sp<AudioPort> getAudioPort() const { return mProfile; }
+    void toAudioPort(struct audio_port *port) const;
+
+    audio_port_handle_t mId;
+    audio_io_handle_t mIoHandle;              // output handle
+    uint32_t mLatency;                  //
+    audio_output_flags_t mFlags;   //
+    audio_devices_t mDevice;                   // current device this output is routed to
+    AudioMix *mPolicyMix;             // non NULL when used by a dynamic policy
+    audio_patch_handle_t mPatchHandle;
+    uint32_t mRefCount[AUDIO_STREAM_CNT]; // number of streams of each type using this output
+    nsecs_t mStopTime[AUDIO_STREAM_CNT];
+    sp<AudioOutputDescriptor> mOutput1;    // used by duplicated outputs: first output
+    sp<AudioOutputDescriptor> mOutput2;    // used by duplicated outputs: second output
+    float mCurVolume[AUDIO_STREAM_CNT];   // current stream volume
+    int mMuteCount[AUDIO_STREAM_CNT];     // mute request counter
+    const sp<IOProfile> mProfile;          // I/O profile this output derives from
+    bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible
+                                        // device selection. See checkDeviceMuteStrategies()
+    uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only)
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
similarity index 69%
rename from services/audiopolicy/AudioPolicyManager.cpp
rename to services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 584e170..53ec0f6 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "AudioPolicyManager"
+#define LOG_TAG "APM::AudioPolicyManager"
 //#define LOG_NDEBUG 0
 
 //#define VERY_VERBOSE_LOGGING
@@ -43,6 +43,7 @@
 #include <hardware/audio.h>
 #include <hardware/audio_effect.h>
 #include <media/AudioParameter.h>
+#include <media/AudioPolicyHelper.h>
 #include <soundtrigger/SoundTrigger.h>
 #include "AudioPolicyManager.h"
 #include "audio_policy_conf.h"
@@ -50,189 +51,34 @@
 namespace android {
 
 // ----------------------------------------------------------------------------
-// Definitions for audio_policy.conf file parsing
-// ----------------------------------------------------------------------------
-
-struct StringToEnum {
-    const char *name;
-    uint32_t value;
-};
-
-#define STRING_TO_ENUM(string) { #string, string }
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-const StringToEnum sDeviceNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER_SAFE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_SCO),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_LINE),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM),
-    STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_AMBIENT),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_ALL_SCO),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_HDMI),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_DEVICE),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_FM_TUNER),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_LINE),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
-    STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
-};
-
-const StringToEnum sOutputFlagNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
-    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
-};
-
-const StringToEnum sInputFlagNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
-    STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
-};
-
-const StringToEnum sFormatNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_FLOAT),
-    STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
-    STRING_TO_ENUM(AUDIO_FORMAT_MP3),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_MAIN),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_SSR),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_LTP),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_SCALABLE),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_ERLC),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_LD),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2),
-    STRING_TO_ENUM(AUDIO_FORMAT_AAC_ELD),
-    STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
-    STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V1),
-    STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V2),
-    STRING_TO_ENUM(AUDIO_FORMAT_OPUS),
-    STRING_TO_ENUM(AUDIO_FORMAT_AC3),
-    STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
-};
-
-const StringToEnum sOutChannelsNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_MONO),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
-    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
-};
-
-const StringToEnum sInChannelsNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
-    STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
-    STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
-};
-
-const StringToEnum sGainModeNameToEnumTable[] = {
-    STRING_TO_ENUM(AUDIO_GAIN_MODE_JOINT),
-    STRING_TO_ENUM(AUDIO_GAIN_MODE_CHANNELS),
-    STRING_TO_ENUM(AUDIO_GAIN_MODE_RAMP),
-};
-
-
-uint32_t AudioPolicyManager::stringToEnum(const struct StringToEnum *table,
-                                              size_t size,
-                                              const char *name)
-{
-    for (size_t i = 0; i < size; i++) {
-        if (strcmp(table[i].name, name) == 0) {
-            ALOGV("stringToEnum() found %s", table[i].name);
-            return table[i].value;
-        }
-    }
-    return 0;
-}
-
-const char *AudioPolicyManager::enumToString(const struct StringToEnum *table,
-                                              size_t size,
-                                              uint32_t value)
-{
-    for (size_t i = 0; i < size; i++) {
-        if (table[i].value == value) {
-            return table[i].name;
-        }
-    }
-    return "";
-}
-
-bool AudioPolicyManager::stringToBool(const char *value)
-{
-    return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0));
-}
-
-
-// ----------------------------------------------------------------------------
 // AudioPolicyInterface implementation
 // ----------------------------------------------------------------------------
 
-
 status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
-                                                          audio_policy_dev_state_t state,
-                                                  const char *device_address)
+                                                      audio_policy_dev_state_t state,
+                                                      const char *device_address,
+                                                      const char *device_name)
 {
-    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
-    // handle legacy remote submix case where the address was not always specified
-    if (deviceDistinguishesOnAddress(device) && (address.length() == 0)) {
-        address = String8("0");
-    }
+    return setDeviceConnectionStateInt(device, state, device_address, device_name);
+}
 
-    ALOGV("setDeviceConnectionState() device: %x, state %d, address %s",
-            device, state, address.string());
+status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
+                                                         audio_policy_dev_state_t state,
+                                                         const char *device_address,
+                                                         const char *device_name)
+{
+    ALOGV("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s",
+-            device, state, device_address, device_name);
 
     // connect/disconnect only 1 device at a time
     if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
 
+    sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address, device_name);
+
     // handle output devices
     if (audio_is_output_device(device)) {
         SortedVector <audio_io_handle_t> outputs;
 
-        sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
-        devDesc->mAddress = address;
         ssize_t index = mAvailableOutputDevices.indexOf(devDesc);
 
         // save a copy of the opened output descriptors before any output is opened or closed
@@ -241,7 +87,7 @@
         switch (state)
         {
         // handle output device connection
-        case AUDIO_POLICY_DEVICE_STATE_AVAILABLE:
+        case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
             if (index >= 0) {
                 ALOGW("setDeviceConnectionState() device already connected: %x", device);
                 return INVALID_OPERATION;
@@ -258,13 +104,12 @@
                     mAvailableOutputDevices.remove(devDesc);
                     return INVALID_OPERATION;
                 }
-                mAvailableOutputDevices[index]->mId = nextUniqueId();
-                mAvailableOutputDevices[index]->mModule = module;
+                mAvailableOutputDevices[index]->attach(module);
             } else {
                 return NO_MEMORY;
             }
 
-            if (checkOutputsForDevice(devDesc, state, outputs, address) != NO_ERROR) {
+            if (checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress) != NO_ERROR) {
                 mAvailableOutputDevices.remove(devDesc);
                 return INVALID_OPERATION;
             }
@@ -273,7 +118,13 @@
                     "checkOutputsForDevice() returned no outputs but status OK");
             ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %zu outputs",
                   outputs.size());
-            break;
+
+            // Send connect to HALs
+            AudioParameter param = AudioParameter(devDesc->mAddress);
+            param.addInt(String8(AUDIO_PARAMETER_DEVICE_CONNECT), device);
+            mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
+
+            } break;
         // handle output device disconnection
         case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
             if (index < 0) {
@@ -283,15 +134,15 @@
 
             ALOGV("setDeviceConnectionState() disconnecting output device %x", device);
 
-            // Set Disconnect to HALs
-            AudioParameter param = AudioParameter(address);
+            // Send Disconnect to HALs
+            AudioParameter param = AudioParameter(devDesc->mAddress);
             param.addInt(String8(AUDIO_PARAMETER_DEVICE_DISCONNECT), device);
             mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
 
             // remove device from available output devices
             mAvailableOutputDevices.remove(devDesc);
 
-            checkOutputsForDevice(devDesc, state, outputs, address);
+            checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress);
             } break;
 
         default:
@@ -348,8 +199,6 @@
     if (audio_is_input_device(device)) {
         SortedVector <audio_io_handle_t> inputs;
 
-        sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
-        devDesc->mAddress = address;
         ssize_t index = mAvailableInputDevices.indexOf(devDesc);
         switch (state)
         {
@@ -365,17 +214,22 @@
                       device);
                 return INVALID_OPERATION;
             }
-            if (checkInputsForDevice(device, state, inputs, address) != NO_ERROR) {
+            if (checkInputsForDevice(device, state, inputs, devDesc->mAddress) != NO_ERROR) {
                 return INVALID_OPERATION;
             }
 
             index = mAvailableInputDevices.add(devDesc);
             if (index >= 0) {
-                mAvailableInputDevices[index]->mId = nextUniqueId();
-                mAvailableInputDevices[index]->mModule = module;
+                mAvailableInputDevices[index]->attach(module);
             } else {
                 return NO_MEMORY;
             }
+
+            // Set connect to HALs
+            AudioParameter param = AudioParameter(devDesc->mAddress);
+            param.addInt(String8(AUDIO_PARAMETER_DEVICE_CONNECT), device);
+            mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
+
         } break;
 
         // handle input device disconnection
@@ -388,11 +242,11 @@
             ALOGV("setDeviceConnectionState() disconnecting input device %x", device);
 
             // Set Disconnect to HALs
-            AudioParameter param = AudioParameter(address);
+            AudioParameter param = AudioParameter(devDesc->mAddress);
             param.addInt(String8(AUDIO_PARAMETER_DEVICE_DISCONNECT), device);
             mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
 
-            checkInputsForDevice(device, state, inputs, address);
+            checkInputsForDevice(device, state, inputs, devDesc->mAddress);
             mAvailableInputDevices.remove(devDesc);
 
         } break;
@@ -420,14 +274,7 @@
 audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device,
                                                   const char *device_address)
 {
-    audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
-    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
-    devDesc->mAddress = (device_address == NULL) ? String8("") : String8(device_address);
-    // handle legacy remote submix case where the address was not always specified
-    if (deviceDistinguishesOnAddress(device) && (devDesc->mAddress.length() == 0)) {
-        devDesc->mAddress = String8("0");
-    }
-    ssize_t index;
+    sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address, "");
     DeviceVector *deviceVector;
 
     if (audio_is_output_device(device)) {
@@ -439,7 +286,7 @@
         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
     }
 
-    index = deviceVector->indexOf(devDesc);
+    ssize_t index = deviceVector->indexOf(devDesc);
     if (index >= 0) {
         return AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
     } else {
@@ -447,6 +294,37 @@
     }
 }
 
+sp<DeviceDescriptor>  AudioPolicyManager::getDeviceDescriptor(const audio_devices_t device,
+                                                              const char *device_address,
+                                                              const char *device_name)
+{
+    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
+    // handle legacy remote submix case where the address was not always specified
+    if (deviceDistinguishesOnAddress(device) && (address.length() == 0)) {
+        address = String8("0");
+    }
+
+    for (size_t i = 0; i < mHwModules.size(); i++) {
+        if (mHwModules[i]->mHandle == 0) {
+            continue;
+        }
+        DeviceVector deviceList =
+                mHwModules[i]->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
+        if (!deviceList.isEmpty()) {
+            return deviceList.itemAt(0);
+        }
+        deviceList = mHwModules[i]->mDeclaredDevices.getDevicesFromType(device);
+        if (!deviceList.isEmpty()) {
+            return deviceList.itemAt(0);
+        }
+    }
+
+    sp<DeviceDescriptor> devDesc =
+            new DeviceDescriptor(String8(device_name != NULL ? device_name : ""), device);
+    devDesc->mAddress = address;
+    return devDesc;
+}
+
 void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs)
 {
     bool createTxPatch = false;
@@ -457,7 +335,7 @@
     audio_patch_handle_t afPatchHandle;
     DeviceVector deviceList;
 
-    audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+    audio_devices_t txDevice = getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
     ALOGV("updateCallRouting device rxDevice %08x txDevice %08x", rxDevice, txDevice);
 
     // release existing RX patch if any
@@ -584,8 +462,14 @@
     if (isInCall()) {
         ALOGV("setPhoneState() in call state management: new state is %d", state);
         for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
+            if (stream == AUDIO_STREAM_PATCH) {
+                continue;
+            }
             handleIncallSonification((audio_stream_type_t)stream, false, true);
         }
+
+        // force reevaluating accessibility routing when call starts
+        mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
     }
 
     // store previous phone state for management of sonification strategy below
@@ -599,18 +483,18 @@
         // force routing command to audio hardware when starting a call
         // even if no device change is needed
         force = true;
-        for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
+        for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) {
             mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] =
-                    sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j];
+                    ApmGains::sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j];
         }
     } else if (isStateInCall(oldState) && !isStateInCall(state)) {
         ALOGV("  Exiting call in setPhoneState()");
         // force routing command to audio hardware when exiting a call
         // even if no device change is needed
         force = true;
-        for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
+        for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) {
             mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] =
-                    sVolumeProfiles[AUDIO_STREAM_DTMF][j];
+                    ApmGains::sVolumeProfiles[AUDIO_STREAM_DTMF][j];
         }
     } else if (isStateInCall(state) && (state != oldState)) {
         ALOGV("  Switching between telephony and VoIP in setPhoneState()");
@@ -681,6 +565,9 @@
     if (isStateInCall(state)) {
         ALOGV("setPhoneState() in call state management: new state is %d", state);
         for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
+            if (stream == AUDIO_STREAM_PATCH) {
+                continue;
+            }
             handleIncallSonification((audio_stream_type_t)stream, true, true);
         }
     }
@@ -798,7 +685,7 @@
 
 // Find a direct output profile compatible with the parameters passed, even if the input flags do
 // not explicitly request a direct output
-sp<AudioPolicyManager::IOProfile> AudioPolicyManager::getProfileForDirectOutput(
+sp<IOProfile> AudioPolicyManager::getProfileForDirectOutput(
                                                                audio_devices_t device,
                                                                uint32_t samplingRate,
                                                                audio_format_t format,
@@ -811,7 +698,7 @@
         }
         for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) {
             sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j];
-            bool found = profile->isCompatibleProfile(device, samplingRate,
+            bool found = profile->isCompatibleProfile(device, String8(""), samplingRate,
                     NULL /*updatedSamplingRate*/, format, channelMask,
                     flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ?
                         AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_DIRECT);
@@ -830,48 +717,113 @@
                                     audio_output_flags_t flags,
                                     const audio_offload_info_t *offloadInfo)
 {
-
     routing_strategy strategy = getStrategy(stream);
     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
     ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x",
           device, stream, samplingRate, format, channelMask, flags);
 
-    return getOutputForDevice(device, stream, samplingRate,format, channelMask, flags,
-            offloadInfo);
+    return getOutputForDevice(device, AUDIO_SESSION_ALLOCATE,
+                              stream, samplingRate,format, channelMask,
+                              flags, offloadInfo);
 }
 
-audio_io_handle_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags,
-                                    const audio_offload_info_t *offloadInfo)
+status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
+                                              audio_io_handle_t *output,
+                                              audio_session_t session,
+                                              audio_stream_type_t *stream,
+                                              uint32_t samplingRate,
+                                              audio_format_t format,
+                                              audio_channel_mask_t channelMask,
+                                              audio_output_flags_t flags,
+                                              const audio_offload_info_t *offloadInfo)
 {
-    if (attr == NULL) {
-        ALOGE("getOutputForAttr() called with NULL audio attributes");
-        return 0;
+    audio_attributes_t attributes;
+    if (attr != NULL) {
+        if (!isValidAttributes(attr)) {
+            ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
+                  attr->usage, attr->content_type, attr->flags,
+                  attr->tags);
+            return BAD_VALUE;
+        }
+        attributes = *attr;
+    } else {
+        if (*stream < AUDIO_STREAM_MIN || *stream >= AUDIO_STREAM_PUBLIC_CNT) {
+            ALOGE("getOutputForAttr():  invalid stream type");
+            return BAD_VALUE;
+        }
+        stream_type_to_audio_attributes(*stream, &attributes);
     }
-    ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x",
-            attr->usage, attr->content_type, attr->tags, attr->flags);
 
-    // TODO this is where filtering for custom policies (rerouting, dynamic sources) will go
-    routing_strategy strategy = (routing_strategy) getStrategyForAttr(attr);
+    for (size_t i = 0; i < mPolicyMixes.size(); i++) {
+        sp<AudioOutputDescriptor> desc;
+        if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_PLAYERS) {
+            for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) {
+                if ((RULE_MATCH_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
+                        mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage == attributes.usage) ||
+                    (RULE_EXCLUDE_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
+                        mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage != attributes.usage)) {
+                    desc = mPolicyMixes[i]->mOutput;
+                    break;
+                }
+                if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
+                        strncmp(attributes.tags + strlen("addr="),
+                                mPolicyMixes[i]->mMix.mRegistrationId.string(),
+                                AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
+                    desc = mPolicyMixes[i]->mOutput;
+                    break;
+                }
+            }
+        } else if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_RECORDERS) {
+            if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
+                    strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
+                    strncmp(attributes.tags + strlen("addr="),
+                            mPolicyMixes[i]->mMix.mRegistrationId.string(),
+                            AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
+                desc = mPolicyMixes[i]->mOutput;
+            }
+        }
+        if (desc != 0) {
+            if (!audio_is_linear_pcm(format)) {
+                return BAD_VALUE;
+            }
+            desc->mPolicyMix = &mPolicyMixes[i]->mMix;
+            *stream = streamTypefromAttributesInt(&attributes);
+            *output = desc->mIoHandle;
+            ALOGV("getOutputForAttr() returns output %d", *output);
+            return NO_ERROR;
+        }
+    }
+    if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
+        ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE");
+        return BAD_VALUE;
+    }
+
+    ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x",
+            attributes.usage, attributes.content_type, attributes.tags, attributes.flags);
+
+    routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
 
-    if ((attr->flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
+    if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
     }
 
     ALOGV("getOutputForAttr() device 0x%x, samplingRate %d, format %x, channelMask %x, flags %x",
           device, samplingRate, format, channelMask, flags);
 
-    audio_stream_type_t stream = streamTypefromAttributesInt(attr);
-    return getOutputForDevice(device, stream, samplingRate, format, channelMask, flags,
-                offloadInfo);
+    *stream = streamTypefromAttributesInt(&attributes);
+    *output = getOutputForDevice(device, session, *stream,
+                                 samplingRate, format, channelMask,
+                                 flags, offloadInfo);
+    if (*output == AUDIO_IO_HANDLE_NONE) {
+        return INVALID_OPERATION;
+    }
+    return NO_ERROR;
 }
 
 audio_io_handle_t AudioPolicyManager::getOutputForDevice(
         audio_devices_t device,
+        audio_session_t session __unused,
         audio_stream_type_t stream,
         uint32_t samplingRate,
         audio_format_t format,
@@ -934,6 +886,10 @@
     if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
         flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
     }
+    // only allow deep buffering for music stream type
+    if (stream != AUDIO_STREAM_MUSIC) {
+        flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
+    }
 
     sp<IOProfile> profile;
 
@@ -1013,6 +969,14 @@
             if (output != AUDIO_IO_HANDLE_NONE) {
                 mpClientInterface->closeOutput(output);
             }
+            // fall back to mixer output if possible when the direct output could not be open
+            if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE) {
+                goto non_direct_output;
+            }
+            // fall back to mixer output if possible when the direct output could not be open
+            if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE) {
+                goto non_direct_output;
+            }
             return AUDIO_IO_HANDLE_NONE;
         }
         outputDesc->mSamplingRate = config.sample_rate;
@@ -1118,7 +1082,7 @@
 
 status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
                                              audio_stream_type_t stream,
-                                             int session)
+                                             audio_session_t session)
 {
     ALOGV("startOutput() output %d, stream %d, session %d", output, stream, session);
     ssize_t index = mOutputs.indexOfKey(output);
@@ -1149,7 +1113,13 @@
     outputDesc->changeRefCount(stream, 1);
 
     if (outputDesc->mRefCount[stream] == 1) {
-        audio_devices_t newDevice = getNewOutputDevice(output, false /*fromCache*/);
+        // starting an output being rerouted?
+        audio_devices_t newDevice;
+        if (outputDesc->mPolicyMix != NULL) {
+            newDevice = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+        } else {
+            newDevice = getNewOutputDevice(output, false /*fromCache*/);
+        }
         routing_strategy strategy = getStrategy(stream);
         bool shouldWait = (strategy == STRATEGY_SONIFICATION) ||
                             (strategy == STRATEGY_SONIFICATION_RESPECTFUL) ||
@@ -1192,6 +1162,22 @@
         // update the outputs if starting an output with a stream that can affect notification
         // routing
         handleNotificationRoutingForStream(stream);
+
+        // Automatically enable the remote submix input when output is started on a re routing mix
+        // of type MIX_TYPE_RECORDERS
+        if (audio_is_remote_submix_device(newDevice) && outputDesc->mPolicyMix != NULL &&
+                outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
+                setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                        AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                        outputDesc->mPolicyMix->mRegistrationId,
+                        "remote-submix");
+        }
+
+        // force reevaluating accessibility routing when ringtone or alarm starts
+        if (strategy == STRATEGY_SONIFICATION) {
+            mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
+        }
+
         if (waitMs > muteWaitMs) {
             usleep((waitMs - muteWaitMs) * 2 * 1000);
         }
@@ -1202,7 +1188,7 @@
 
 status_t AudioPolicyManager::stopOutput(audio_io_handle_t output,
                                             audio_stream_type_t stream,
-                                            int session)
+                                            audio_session_t session)
 {
     ALOGV("stopOutput() output %d, stream %d, session %d", output, stream, session);
     ssize_t index = mOutputs.indexOfKey(output);
@@ -1226,6 +1212,17 @@
         outputDesc->changeRefCount(stream, -1);
         // store time at which the stream was stopped - see isStreamActive()
         if (outputDesc->mRefCount[stream] == 0) {
+            // Automatically disable the remote submix input when output is stopped on a
+            // re routing mix of type MIX_TYPE_RECORDERS
+            if (audio_is_remote_submix_device(outputDesc->mDevice) &&
+                    outputDesc->mPolicyMix != NULL &&
+                    outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
+                setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                        AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                        outputDesc->mPolicyMix->mRegistrationId,
+                        "remote-submix");
+            }
+
             outputDesc->mStopTime[stream] = systemTime();
             audio_devices_t newDevice = getNewOutputDevice(output, false /*fromCache*/);
             // delay the device switch by twice the latency because stopOutput() is executed when
@@ -1260,7 +1257,9 @@
     }
 }
 
-void AudioPolicyManager::releaseOutput(audio_io_handle_t output)
+void AudioPolicyManager::releaseOutput(audio_io_handle_t output,
+                                       audio_stream_type_t stream __unused,
+                                       audio_session_t session __unused)
 {
     ALOGV("releaseOutput() %d", output);
     ssize_t index = mOutputs.indexOfKey(output);
@@ -1303,79 +1302,121 @@
 }
 
 
-audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_session_t session,
-                                    audio_input_flags_t flags)
+status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
+                                             audio_io_handle_t *input,
+                                             audio_session_t session,
+                                             uint32_t samplingRate,
+                                             audio_format_t format,
+                                             audio_channel_mask_t channelMask,
+                                             audio_input_flags_t flags,
+                                             input_type_t *inputType)
 {
-    ALOGV("getInput() inputSource %d, samplingRate %d, format %d, channelMask %x, session %d, "
-          "flags %#x",
-          inputSource, samplingRate, format, channelMask, session, flags);
+    ALOGV("getInputForAttr() source %d, samplingRate %d, format %d, channelMask %x,"
+            "session %d, flags %#x",
+          attr->source, samplingRate, format, channelMask, session, flags);
 
-    audio_devices_t device = getDeviceForInputSource(inputSource);
-
-    if (device == AUDIO_DEVICE_NONE) {
-        ALOGW("getInput() could not find device for inputSource %d", inputSource);
-        return AUDIO_IO_HANDLE_NONE;
-    }
-
-    // adapt channel selection to input source
-    switch (inputSource) {
-    case AUDIO_SOURCE_VOICE_UPLINK:
-        channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK;
-        break;
-    case AUDIO_SOURCE_VOICE_DOWNLINK:
-        channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK;
-        break;
-    case AUDIO_SOURCE_VOICE_CALL:
-        channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK;
-        break;
-    default:
-        break;
-    }
-
-    audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
+    *input = AUDIO_IO_HANDLE_NONE;
+    *inputType = API_INPUT_INVALID;
+    audio_devices_t device;
+    // handle legacy remote submix case where the address was not always specified
+    String8 address = String8("");
     bool isSoundTrigger = false;
-    audio_source_t halInputSource = inputSource;
-    if (inputSource == AUDIO_SOURCE_HOTWORD) {
-        ssize_t index = mSoundTriggerSessions.indexOfKey(session);
-        if (index >= 0) {
-            input = mSoundTriggerSessions.valueFor(session);
-            isSoundTrigger = true;
-            flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_HW_HOTWORD);
-            ALOGV("SoundTrigger capture on session %d input %d", session, input);
+    audio_source_t inputSource = attr->source;
+    audio_source_t halInputSource;
+    AudioMix *policyMix = NULL;
+
+    if (inputSource == AUDIO_SOURCE_DEFAULT) {
+        inputSource = AUDIO_SOURCE_MIC;
+    }
+    halInputSource = inputSource;
+
+    if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX &&
+            strncmp(attr->tags, "addr=", strlen("addr=")) == 0) {
+        device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+        address = String8(attr->tags + strlen("addr="));
+        ssize_t index = mPolicyMixes.indexOfKey(address);
+        if (index < 0) {
+            ALOGW("getInputForAttr() no policy for address %s", address.string());
+            return BAD_VALUE;
+        }
+        if (mPolicyMixes[index]->mMix.mMixType != MIX_TYPE_PLAYERS) {
+            ALOGW("getInputForAttr() bad policy mix type for address %s", address.string());
+            return BAD_VALUE;
+        }
+        policyMix = &mPolicyMixes[index]->mMix;
+        *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
+    } else {
+        device = getDeviceAndMixForInputSource(inputSource, &policyMix);
+        if (device == AUDIO_DEVICE_NONE) {
+            ALOGW("getInputForAttr() could not find device for source %d", inputSource);
+            return BAD_VALUE;
+        }
+        if (policyMix != NULL) {
+            address = policyMix->mRegistrationId;
+            if (policyMix->mMixType == MIX_TYPE_RECORDERS) {
+                // there is an external policy, but this input is attached to a mix of recorders,
+                // meaning it receives audio injected into the framework, so the recorder doesn't
+                // know about it and is therefore considered "legacy"
+                *inputType = API_INPUT_LEGACY;
+            } else {
+                // recording a mix of players defined by an external policy, we're rerouting for
+                // an external policy
+                *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
+            }
+        } else if (audio_is_remote_submix_device(device)) {
+            address = String8("0");
+            *inputType = API_INPUT_MIX_CAPTURE;
         } else {
-            halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
+            *inputType = API_INPUT_LEGACY;
+        }
+        // adapt channel selection to input source
+        switch (inputSource) {
+        case AUDIO_SOURCE_VOICE_UPLINK:
+            channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK;
+            break;
+        case AUDIO_SOURCE_VOICE_DOWNLINK:
+            channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK;
+            break;
+        case AUDIO_SOURCE_VOICE_CALL:
+            channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK;
+            break;
+        default:
+            break;
+        }
+        if (inputSource == AUDIO_SOURCE_HOTWORD) {
+            ssize_t index = mSoundTriggerSessions.indexOfKey(session);
+            if (index >= 0) {
+                *input = mSoundTriggerSessions.valueFor(session);
+                isSoundTrigger = true;
+                flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_HW_HOTWORD);
+                ALOGV("SoundTrigger capture on session %d input %d", session, *input);
+            } else {
+                halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
+            }
         }
     }
 
-    sp<IOProfile> profile = getInputProfile(device,
-                                         samplingRate,
-                                         format,
-                                         channelMask,
-                                         flags);
+    sp<IOProfile> profile = getInputProfile(device, address,
+                                            samplingRate, format, channelMask,
+                                            flags);
     if (profile == 0) {
         //retry without flags
         audio_input_flags_t log_flags = flags;
         flags = AUDIO_INPUT_FLAG_NONE;
-        profile = getInputProfile(device,
-                                 samplingRate,
-                                 format,
-                                 channelMask,
-                                 flags);
+        profile = getInputProfile(device, address,
+                                  samplingRate, format, channelMask,
+                                  flags);
         if (profile == 0) {
-            ALOGW("getInput() could not find profile for device 0x%X, samplingRate %u, format %#x, "
-                    "channelMask 0x%X, flags %#x",
+            ALOGW("getInputForAttr() could not find profile for device 0x%X, samplingRate %u,"
+                    "format %#x, channelMask 0x%X, flags %#x",
                     device, samplingRate, format, channelMask, log_flags);
-            return AUDIO_IO_HANDLE_NONE;
+            return BAD_VALUE;
         }
     }
 
     if (profile->mModule->mHandle == 0) {
-        ALOGE("getInput(): HW module %s not opened", profile->mModule->mName);
-        return AUDIO_IO_HANDLE_NONE;
+        ALOGE("getInputForAttr(): HW module %s not opened", profile->mModule->mName);
+        return NO_INIT;
     }
 
     audio_config_t config = AUDIO_CONFIG_INITIALIZER;
@@ -1383,11 +1424,8 @@
     config.channel_mask = channelMask;
     config.format = format;
 
-    // handle legacy remote submix case where the address was not always specified
-    String8 address = deviceDistinguishesOnAddress(device) ? String8("0") : String8("");
-
     status_t status = mpClientInterface->openInput(profile->mModule->mHandle,
-                                                   &input,
+                                                   input,
                                                    &config,
                                                    &device,
                                                    address,
@@ -1395,16 +1433,16 @@
                                                    flags);
 
     // only accept input with the exact requested set of parameters
-    if (status != NO_ERROR ||
+    if (status != NO_ERROR || *input == AUDIO_IO_HANDLE_NONE ||
         (samplingRate != config.sample_rate) ||
         (format != config.format) ||
         (channelMask != config.channel_mask)) {
-        ALOGW("getInput() failed opening input: samplingRate %d, format %d, channelMask %x",
+        ALOGW("getInputForAttr() failed opening input: samplingRate %d, format %d, channelMask %x",
                 samplingRate, format, channelMask);
-        if (input != AUDIO_IO_HANDLE_NONE) {
-            mpClientInterface->closeInput(input);
+        if (*input != AUDIO_IO_HANDLE_NONE) {
+            mpClientInterface->closeInput(*input);
         }
-        return AUDIO_IO_HANDLE_NONE;
+        return BAD_VALUE;
     }
 
     sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile);
@@ -1417,10 +1455,13 @@
     inputDesc->mDevice = device;
     inputDesc->mSessions.add(session);
     inputDesc->mIsSoundTrigger = isSoundTrigger;
+    inputDesc->mPolicyMix = policyMix;
 
-    addInput(input, inputDesc);
+    ALOGV("getInputForAttr() returns input type = %d", inputType);
+
+    addInput(*input, inputDesc);
     mpClientInterface->onAudioPortListUpdate();
-    return input;
+    return NO_ERROR;
 }
 
 status_t AudioPolicyManager::startInput(audio_io_handle_t input,
@@ -1467,11 +1508,21 @@
         }
         setInputDevice(input, getNewInputDevice(input), true /* force */);
 
-        // Automatically enable the remote submix output when input is started.
+        // automatically enable the remote submix output when input is started if not
+        // used by a policy mix of type MIX_TYPE_RECORDERS
         // For remote submix (a virtual device), we open only one input per capture request.
         if (audio_is_remote_submix_device(inputDesc->mDevice)) {
-            setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-                    AUDIO_POLICY_DEVICE_STATE_AVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS);
+            String8 address = String8("");
+            if (inputDesc->mPolicyMix == NULL) {
+                address = String8("0");
+            } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
+                address = inputDesc->mPolicyMix->mRegistrationId;
+            }
+            if (address != "") {
+                setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                        AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                        address, "remote-submix");
+            }
         }
     }
 
@@ -1506,10 +1557,20 @@
     inputDesc->mRefCount--;
     if (inputDesc->mRefCount == 0) {
 
-        // automatically disable the remote submix output when input is stopped
+        // automatically disable the remote submix output when input is stopped if not
+        // used by a policy mix of type MIX_TYPE_RECORDERS
         if (audio_is_remote_submix_device(inputDesc->mDevice)) {
-            setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-                    AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS);
+            String8 address = String8("");
+            if (inputDesc->mPolicyMix == NULL) {
+                address = String8("0");
+            } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
+                address = inputDesc->mPolicyMix->mRegistrationId;
+            }
+            if (address != "") {
+                setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                                         AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                                         address, "remote-submix");
+            }
         }
 
         resetInputDevice(input);
@@ -1587,6 +1648,11 @@
     }
     mStreams[stream].mIndexMin = indexMin;
     mStreams[stream].mIndexMax = indexMax;
+    //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
+    if (stream == AUDIO_STREAM_MUSIC) {
+        mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMin = indexMin;
+        mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMax = indexMax;
+    }
 }
 
 status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
@@ -1617,19 +1683,32 @@
     // update volume on all outputs whose current device is also selected by the same
     // strategy as the device specified by the caller
     audio_devices_t strategyDevice = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);
-    if ((device != AUDIO_DEVICE_OUT_DEFAULT) && (device & strategyDevice) == 0) {
+
+
+    //FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
+    audio_devices_t accessibilityDevice = AUDIO_DEVICE_NONE;
+    if (stream == AUDIO_STREAM_MUSIC) {
+        mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexCur.add(device, index);
+        accessibilityDevice = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, true /*fromCache*/);
+    }
+    if ((device != AUDIO_DEVICE_OUT_DEFAULT) &&
+            (device & (strategyDevice | accessibilityDevice)) == 0) {
         return NO_ERROR;
     }
     status_t status = NO_ERROR;
     for (size_t i = 0; i < mOutputs.size(); i++) {
         audio_devices_t curDevice =
-                getDeviceForVolume(mOutputs.valueAt(i)->device());
+                ApmGains::getDeviceForVolume(mOutputs.valueAt(i)->device());
         if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & strategyDevice) != 0)) {
             status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);
             if (volStatus != NO_ERROR) {
                 status = volStatus;
             }
         }
+        if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & accessibilityDevice) != 0)) {
+            status_t volStatus = checkAndSetVolume(AUDIO_STREAM_ACCESSIBILITY,
+                                                   index, mOutputs.keyAt(i), curDevice);
+        }
     }
     return status;
 }
@@ -1649,7 +1728,7 @@
     if (device == AUDIO_DEVICE_OUT_DEFAULT) {
         device = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);
     }
-    device = getDeviceForVolume(device);
+    device = ApmGains::getDeviceForVolume(device);
 
     *index =  mStreams[stream].getVolumeIndex(device);
     ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index);
@@ -1849,7 +1928,11 @@
         const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
         if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
                 outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
-            return true;
+            // do not consider re routing (when the output is going to a dynamic policy)
+            // as "remote playback"
+            if (outputDesc->mPolicyMix == NULL) {
+                return true;
+            }
         }
     }
     return false;
@@ -1859,16 +1942,148 @@
 {
     for (size_t i = 0; i < mInputs.size(); i++) {
         const sp<AudioInputDescriptor>  inputDescriptor = mInputs.valueAt(i);
-        if ((inputDescriptor->mInputSource == (int)source ||
-                (source == AUDIO_SOURCE_VOICE_RECOGNITION &&
-                 inputDescriptor->mInputSource == AUDIO_SOURCE_HOTWORD))
-             && (inputDescriptor->mRefCount > 0)) {
+        if (inputDescriptor->mRefCount == 0) {
+            continue;
+        }
+        if (inputDescriptor->mInputSource == (int)source) {
             return true;
         }
+        // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it
+        // corresponds to an active capture triggered by a hardware hotword recognition
+        if ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
+                 (inputDescriptor->mInputSource == AUDIO_SOURCE_HOTWORD)) {
+            // FIXME: we should not assume that the first session is the active one and keep
+            // activity count per session. Same in startInput().
+            ssize_t index = mSoundTriggerSessions.indexOfKey(inputDescriptor->mSessions.itemAt(0));
+            if (index >= 0) {
+                return true;
+            }
+        }
     }
     return false;
 }
 
+// Register a list of custom mixes with their attributes and format.
+// When a mix is registered, corresponding input and output profiles are
+// added to the remote submix hw module. The profile contains only the
+// parameters (sampling rate, format...) specified by the mix.
+// The corresponding input remote submix device is also connected.
+//
+// When a remote submix device is connected, the address is checked to select the
+// appropriate profile and the corresponding input or output stream is opened.
+//
+// When capture starts, getInputForAttr() will:
+//  - 1 look for a mix matching the address passed in attribtutes tags if any
+//  - 2 if none found, getDeviceForInputSource() will:
+//     - 2.1 look for a mix matching the attributes source
+//     - 2.2 if none found, default to device selection by policy rules
+// At this time, the corresponding output remote submix device is also connected
+// and active playback use cases can be transferred to this mix if needed when reconnecting
+// after AudioTracks are invalidated
+//
+// When playback starts, getOutputForAttr() will:
+//  - 1 look for a mix matching the address passed in attribtutes tags if any
+//  - 2 if none found, look for a mix matching the attributes usage
+//  - 3 if none found, default to device and output selection by policy rules.
+
+status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes)
+{
+    sp<HwModule> module;
+    for (size_t i = 0; i < mHwModules.size(); i++) {
+        if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[i]->mName) == 0 &&
+                mHwModules[i]->mHandle != 0) {
+            module = mHwModules[i];
+            break;
+        }
+    }
+
+    if (module == 0) {
+        return INVALID_OPERATION;
+    }
+
+    ALOGV("registerPolicyMixes() num mixes %d", mixes.size());
+
+    for (size_t i = 0; i < mixes.size(); i++) {
+        String8 address = mixes[i].mRegistrationId;
+        ssize_t index = mPolicyMixes.indexOfKey(address);
+        if (index >= 0) {
+            ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string());
+            continue;
+        }
+        audio_config_t outputConfig = mixes[i].mFormat;
+        audio_config_t inputConfig = mixes[i].mFormat;
+        // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in
+        // stereo and let audio flinger do the channel conversion if needed.
+        outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+        inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
+        module->addOutputProfile(address, &outputConfig,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
+        module->addInputProfile(address, &inputConfig,
+                                 AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
+        sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
+        policyMix->mMix = mixes[i];
+        mPolicyMixes.add(address, policyMix);
+        if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
+            setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                                     AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                                     address.string(), "remote-submix");
+        } else {
+            setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                                     AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                                     address.string(), "remote-submix");
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes)
+{
+    sp<HwModule> module;
+    for (size_t i = 0; i < mHwModules.size(); i++) {
+        if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[i]->mName) == 0 &&
+                mHwModules[i]->mHandle != 0) {
+            module = mHwModules[i];
+            break;
+        }
+    }
+
+    if (module == 0) {
+        return INVALID_OPERATION;
+    }
+
+    ALOGV("unregisterPolicyMixes() num mixes %d", mixes.size());
+
+    for (size_t i = 0; i < mixes.size(); i++) {
+        String8 address = mixes[i].mRegistrationId;
+        ssize_t index = mPolicyMixes.indexOfKey(address);
+        if (index < 0) {
+            ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
+            continue;
+        }
+
+        mPolicyMixes.removeItemsAt(index);
+
+        if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) ==
+                                             AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
+        {
+            setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                                     AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                                     address.string(), "remote-submix");
+        }
+
+        if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) ==
+                                             AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
+        {
+            setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                                     AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                                     address.string(), "remote-submix");
+        }
+        module->removeOutputProfile(address);
+        module->removeInputProfile(address);
+    }
+    return NO_ERROR;
+}
+
 
 status_t AudioPolicyManager::dump(int fd)
 {
@@ -2097,7 +2312,7 @@
     return NO_ERROR;
 }
 
-sp<AudioPolicyManager::AudioOutputDescriptor> AudioPolicyManager::getOutputFromId(
+sp<AudioOutputDescriptor> AudioPolicyManager::getOutputFromId(
                                                                     audio_port_handle_t id) const
 {
     sp<AudioOutputDescriptor> outputDesc = NULL;
@@ -2110,7 +2325,7 @@
     return outputDesc;
 }
 
-sp<AudioPolicyManager::AudioInputDescriptor> AudioPolicyManager::getInputFromId(
+sp<AudioInputDescriptor> AudioPolicyManager::getInputFromId(
                                                                     audio_port_handle_t id) const
 {
     sp<AudioInputDescriptor> inputDesc = NULL;
@@ -2123,7 +2338,7 @@
     return inputDesc;
 }
 
-sp <AudioPolicyManager::HwModule> AudioPolicyManager::getModuleForDevice(
+sp <HwModule> AudioPolicyManager::getModuleForDevice(
                                                                     audio_devices_t device) const
 {
     sp <HwModule> module;
@@ -2151,7 +2366,7 @@
     return module;
 }
 
-sp <AudioPolicyManager::HwModule> AudioPolicyManager::getModuleFromName(const char *name) const
+sp <HwModule> AudioPolicyManager::getModuleFromName(const char *name) const
 {
     sp <HwModule> module;
 
@@ -2269,6 +2484,7 @@
             }
 
             if (!outputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType,
+                                                           devDesc->mAddress,
                                                            patch->sources[0].sample_rate,
                                                          NULL,  // updatedSamplingRate
                                                          patch->sources[0].format,
@@ -2323,13 +2539,14 @@
             }
 
             if (!inputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType,
-                                                         patch->sinks[0].sample_rate,
-                                                         NULL, /*updatedSampleRate*/
-                                                         patch->sinks[0].format,
-                                                         patch->sinks[0].channel_mask,
-                                                         // FIXME for the parameter type,
-                                                         // and the NONE
-                                                         (audio_output_flags_t)
+                                                          devDesc->mAddress,
+                                                          patch->sinks[0].sample_rate,
+                                                          NULL, /*updatedSampleRate*/
+                                                          patch->sinks[0].format,
+                                                          patch->sinks[0].channel_mask,
+                                                          // FIXME for the parameter type,
+                                                          // and the NONE
+                                                          (audio_output_flags_t)
                                                             AUDIO_INPUT_FLAG_NONE)) {
                 return INVALID_OPERATION;
             }
@@ -2596,13 +2813,10 @@
 
 void AudioPolicyManager::clearAudioPatches(uid_t uid)
 {
-    for (ssize_t i = 0; i < (ssize_t)mAudioPatches.size(); i++)  {
+    for (ssize_t i = (ssize_t)mAudioPatches.size() - 1; i >= 0; i--)  {
         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(i);
         if (patchDesc->mUid == uid) {
-            // releaseAudioPatch() removes the patch from mAudioPatches
-            if (releaseAudioPatch(mAudioPatches.keyAt(i), uid) == NO_ERROR) {
-                i--;
-            }
+            releaseAudioPatch(mAudioPatches.keyAt(i), uid);
         }
     }
 }
@@ -2613,7 +2827,7 @@
 {
     *session = (audio_session_t)mpClientInterface->newAudioUniqueId();
     *ioHandle = (audio_io_handle_t)mpClientInterface->newAudioUniqueId();
-    *device = getDeviceForInputSource(AUDIO_SOURCE_HOTWORD);
+    *device = getDeviceAndMixForInputSource(AUDIO_SOURCE_HOTWORD);
 
     mSoundTriggerSessions.add(*session, *ioHandle);
 
@@ -2677,6 +2891,8 @@
     return android_atomic_inc(&mAudioPortGeneration);
 }
 
+int32_t volatile AudioPolicyManager::mNextUniqueId = 1;
+
 AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
     :
 #ifdef AUDIO_POLICY_TEST
@@ -2687,7 +2903,7 @@
     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
     mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
     mA2dpSuspended(false),
-    mSpeakerDrcEnabled(false), mNextUniqueId(1),
+    mSpeakerDrcEnabled(false),
     mAudioPortGeneration(1),
     mBeaconMuteRefCount(0),
     mBeaconPlayingRefCount(0),
@@ -2700,7 +2916,7 @@
         mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
     }
 
-    mDefaultOutputDevice = new DeviceDescriptor(String8(""), AUDIO_DEVICE_OUT_SPEAKER);
+    mDefaultOutputDevice = new DeviceDescriptor(String8("Speaker"), AUDIO_DEVICE_OUT_SPEAKER);
     if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
         if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
             ALOGE("could not load audio policy configuration file, setting defaults");
@@ -2783,9 +2999,8 @@
                     ssize_t index =
                             mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
-                    if ((index >= 0) && (mAvailableOutputDevices[index]->mId == 0)) {
-                        mAvailableOutputDevices[index]->mId = nextUniqueId();
-                        mAvailableOutputDevices[index]->mModule = mHwModules[i];
+                    if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
+                        mAvailableOutputDevices[index]->attach(mHwModules[i]);
                     }
                 }
                 if (mPrimaryOutput == 0 &&
@@ -2852,9 +3067,8 @@
                     ssize_t index =
                             mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
-                    if ((index >= 0) && (mAvailableInputDevices[index]->mId == 0)) {
-                        mAvailableInputDevices[index]->mId = nextUniqueId();
-                        mAvailableInputDevices[index]->mModule = mHwModules[i];
+                    if (index >= 0 && !mAvailableInputDevices[index]->isAttached()) {
+                        mAvailableInputDevices[index]->attach(mHwModules[i]);
                     }
                 }
                 mpClientInterface->closeInput(input);
@@ -2867,7 +3081,7 @@
     }
     // make sure all attached devices have been allocated a unique ID
     for (size_t i = 0; i  < mAvailableOutputDevices.size();) {
-        if (mAvailableOutputDevices[i]->mId == 0) {
+        if (!mAvailableOutputDevices[i]->isAttached()) {
             ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mDeviceType);
             mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
             continue;
@@ -2875,7 +3089,7 @@
         i++;
     }
     for (size_t i = 0; i  < mAvailableInputDevices.size();) {
-        if (mAvailableInputDevices[i]->mId == 0) {
+        if (!mAvailableInputDevices[i]->isAttached()) {
             ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mDeviceType);
             mAvailableInputDevices.remove(mAvailableInputDevices[i]);
             continue;
@@ -3115,29 +3329,15 @@
 }
 
 void AudioPolicyManager::findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/,
+        const audio_devices_t device /*in*/,
         const String8 address /*in*/,
         SortedVector<audio_io_handle_t>& outputs /*out*/) {
-    // look for a match on the given address on the addresses of the outputs:
-    // find the address by finding the patch that maps to this output
-    ssize_t patchIdx = mAudioPatches.indexOfKey(desc->mPatchHandle);
-    //ALOGV("    inspecting output %d (patch %d) for supported device=0x%x",
-    //        outputIdx, patchIdx,  desc->mProfile->mSupportedDevices.types());
-    if (patchIdx >= 0) {
-        const sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patchIdx);
-        const int numSinks = patchDesc->mPatch.num_sinks;
-        for (ssize_t j=0; j < numSinks; j++) {
-            if (patchDesc->mPatch.sinks[j].type == AUDIO_PORT_TYPE_DEVICE) {
-                const char* patchAddr =
-                        patchDesc->mPatch.sinks[j].ext.device.address;
-                if (strncmp(patchAddr,
-                        address.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
-                    ALOGV("findIoHandlesByAddress(): adding opened output %d on same address %s",
-                            desc->mIoHandle,  patchDesc->mPatch.sinks[j].ext.device.address);
-                    outputs.add(desc->mIoHandle);
-                    break;
-                }
-            }
-        }
+    sp<DeviceDescriptor> devDesc =
+        desc->mProfile->mSupportedDevices.getDevice(device, address);
+    if (devDesc != 0) {
+        ALOGV("findIoHandlesByAddress(): adding opened output %d on same address %s",
+              desc->mIoHandle, address.string());
+        outputs.add(desc->mIoHandle);
     }
 }
 
@@ -3161,7 +3361,7 @@
                     outputs.add(mOutputs.keyAt(i));
                 } else {
                     ALOGV("  checking address match due to device 0x%x", device);
-                    findIoHandlesByAddress(desc, address, outputs);
+                    findIoHandlesByAddress(desc, device, address, outputs);
                 }
             }
         }
@@ -3174,9 +3374,13 @@
             }
             for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
             {
-                if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices.types() & device) {
-                    ALOGV("checkOutputsForDevice(): adding profile %zu from module %zu", j, i);
-                    profiles.add(mHwModules[i]->mOutputProfiles[j]);
+                sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j];
+                if (profile->mSupportedDevices.types() & device) {
+                    if (!deviceDistinguishesOnAddress(device) ||
+                            address == profile->mSupportedDevices[0]->mAddress) {
+                        profiles.add(profile);
+                        ALOGV("checkOutputsForDevice(): adding profile %zu from module %zu", j, i);
+                    }
                 }
             }
         }
@@ -3308,7 +3512,18 @@
 
                 if (output != AUDIO_IO_HANDLE_NONE) {
                     addOutput(output, desc);
-                    if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) {
+                    if (deviceDistinguishesOnAddress(device) && address != "0") {
+                        ssize_t index = mPolicyMixes.indexOfKey(address);
+                        if (index >= 0) {
+                            mPolicyMixes[index]->mOutput = desc;
+                            desc->mPolicyMix = &mPolicyMixes[index]->mMix;
+                        } else {
+                            ALOGE("checkOutputsForDevice() cannot find policy for address %s",
+                                  address.string());
+                        }
+                    } else if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) {
+                        // no duplicated output for direct outputs and
+                        // outputs used by dynamic policy mixes
                         audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
 
                         // set initial stream volume for device
@@ -3371,15 +3586,15 @@
         for (size_t i = 0; i < mOutputs.size(); i++) {
             desc = mOutputs.valueAt(i);
             if (!desc->isDuplicated()) {
-                if  (!(desc->mProfile->mSupportedDevices.types()
+                // exact match on device
+                if (deviceDistinguishesOnAddress(device) &&
+                        (desc->mProfile->mSupportedDevices.types() == device)) {
+                    findIoHandlesByAddress(desc, device, address, outputs);
+                } else if (!(desc->mProfile->mSupportedDevices.types()
                         & mAvailableOutputDevices.types())) {
                     ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
                             mOutputs.keyAt(i));
                     outputs.add(mOutputs.keyAt(i));
-                } else if (deviceDistinguishesOnAddress(device) &&
-                        // exact match on device
-                        (desc->mProfile->mSupportedDevices.types() == device)) {
-                    findIoHandlesByAddress(desc, address, outputs);
                 }
             }
         }
@@ -3441,11 +3656,15 @@
                  profile_index < mHwModules[module_idx]->mInputProfiles.size();
                  profile_index++)
             {
-                if (mHwModules[module_idx]->mInputProfiles[profile_index]->mSupportedDevices.types()
-                        & (device & ~AUDIO_DEVICE_BIT_IN)) {
-                    ALOGV("checkInputsForDevice(): adding profile %zu from module %zu",
-                          profile_index, module_idx);
-                    profiles.add(mHwModules[module_idx]->mInputProfiles[profile_index]);
+                sp<IOProfile> profile = mHwModules[module_idx]->mInputProfiles[profile_index];
+
+                if (profile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) {
+                    if (!deviceDistinguishesOnAddress(device) ||
+                            address == profile->mSupportedDevices[0]->mAddress) {
+                        profiles.add(profile);
+                        ALOGV("checkInputsForDevice(): adding profile %zu from module %zu",
+                              profile_index, module_idx);
+                    }
                 }
             }
         }
@@ -3563,7 +3782,8 @@
         // check if one opened input is not needed any more after disconnecting one device
         for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
             desc = mInputs.valueAt(input_index);
-            if (!(desc->mProfile->mSupportedDevices.types() & mAvailableInputDevices.types())) {
+            if (!(desc->mProfile->mSupportedDevices.types() & mAvailableInputDevices.types() &
+                    ~AUDIO_DEVICE_BIT_IN)) {
                 ALOGV("checkInputsForDevice(): disconnecting adding input %d",
                       mInputs.keyAt(input_index));
                 inputs.add(mInputs.keyAt(input_index));
@@ -3578,7 +3798,7 @@
                  profile_index < mHwModules[module_index]->mInputProfiles.size();
                  profile_index++) {
                 sp<IOProfile> profile = mHwModules[module_index]->mInputProfiles[profile_index];
-                if (profile->mSupportedDevices.types() & device) {
+                if (profile->mSupportedDevices.types() & device & ~AUDIO_DEVICE_BIT_IN) {
                     ALOGV("checkInputsForDevice(): clearing direct input profile %zu on module %zu",
                           profile_index, module_index);
                     if (profile->mSamplingRates[0] == 0) {
@@ -3612,6 +3832,12 @@
         return;
     }
 
+    for (size_t i = 0; i < mPolicyMixes.size(); i++) {
+        if (mPolicyMixes[i]->mOutput == outputDesc) {
+            mPolicyMixes[i]->mOutput.clear();
+        }
+    }
+
     // look for duplicated outputs connected to the output being removed.
     for (size_t i = 0; i < mOutputs.size(); i++) {
         sp<AudioOutputDescriptor> dupOutputDesc = mOutputs.valueAt(i);
@@ -3721,6 +3947,24 @@
     SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs);
     SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs);
 
+    // also take into account external policy-related changes: add all outputs which are
+    // associated with policies in the "before" and "after" output vectors
+    ALOGVV("checkOutputForStrategy(): policy related outputs");
+    for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) {
+        const sp<AudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i);
+        if (desc != 0 && desc->mPolicyMix != NULL) {
+            srcOutputs.add(desc->mIoHandle);
+            ALOGVV(" previous outputs: adding %d", desc->mIoHandle);
+        }
+    }
+    for (size_t i = 0 ; i < mOutputs.size() ; i++) {
+        const sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
+        if (desc != 0 && desc->mPolicyMix != NULL) {
+            dstOutputs.add(desc->mIoHandle);
+            ALOGVV(" new outputs: adding %d", desc->mIoHandle);
+        }
+    }
+
     if (!vectorsEqual(srcOutputs,dstOutputs)) {
         ALOGV("checkOutputForStrategy() strategy %d, moving from output %d to output %d",
               strategy, srcOutputs[0], dstOutputs[0]);
@@ -3754,6 +3998,9 @@
         }
         // Move tracks associated to this strategy from previous output to new output
         for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
+            if (i == AUDIO_STREAM_PATCH) {
+                continue;
+            }
             if (getStrategy((audio_stream_type_t)i) == strategy) {
                 mpClientInterface->invalidateStream((audio_stream_type_t)i);
             }
@@ -3770,8 +4017,10 @@
         checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
     checkOutputForStrategy(STRATEGY_SONIFICATION);
     checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL);
+    checkOutputForStrategy(STRATEGY_ACCESSIBILITY);
     checkOutputForStrategy(STRATEGY_MEDIA);
     checkOutputForStrategy(STRATEGY_DTMF);
+    checkOutputForStrategy(STRATEGY_REROUTING);
 }
 
 audio_io_handle_t AudioPolicyManager::getA2dpOutput()
@@ -3795,7 +4044,9 @@
     }
 
     bool isScoConnected =
-            (mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) != 0;
+            ((mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET &
+                    ~AUDIO_DEVICE_BIT_IN) != 0) ||
+            ((mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_ALL_SCO) != 0);
     // suspend A2DP output if:
     //      (NOT already suspended) &&
     //      ((SCO device is connected &&
@@ -3858,11 +4109,13 @@
     //      use device for strategy sonification
     // 5: the strategy "respectful" sonification is active on the output:
     //      use device for strategy "respectful" sonification
-    // 6: the strategy media is active on the output:
+    // 6: the strategy accessibility is active on the output:
+    //      use device for strategy accessibility
+    // 7: the strategy media is active on the output:
     //      use device for strategy media
-    // 7: the strategy DTMF is active on the output:
+    // 8: the strategy DTMF is active on the output:
     //      use device for strategy DTMF
-    // 8: the strategy for beacon, a.k.a. "transmitted through speaker" is active on the output:
+    // 9: the strategy for beacon, a.k.a. "transmitted through speaker" is active on the output:
     //      use device for strategy t-t-s
     if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE) &&
         mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
@@ -3876,12 +4129,16 @@
         device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
     } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION_RESPECTFUL)) {
         device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
+    } else if (outputDesc->isStrategyActive(STRATEGY_ACCESSIBILITY)) {
+        device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
     } else if (outputDesc->isStrategyActive(STRATEGY_MEDIA)) {
         device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
     } else if (outputDesc->isStrategyActive(STRATEGY_DTMF)) {
         device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
     } else if (outputDesc->isStrategyActive(STRATEGY_TRANSMITTED_THROUGH_SPEAKER)) {
         device = getDeviceForStrategy(STRATEGY_TRANSMITTED_THROUGH_SPEAKER, fromCache);
+    } else if (outputDesc->isStrategyActive(STRATEGY_REROUTING)) {
+        device = getDeviceForStrategy(STRATEGY_REROUTING, fromCache);
     }
 
     ALOGV("getNewOutputDevice() selected device %x", device);
@@ -3902,7 +4159,7 @@
         }
     }
 
-    audio_devices_t device = getDeviceForInputSource(inputDesc->mInputSource);
+    audio_devices_t device = getDeviceAndMixForInputSource(inputDesc->mInputSource);
 
     ALOGV("getNewInputDevice() selected device %x", device);
     return device;
@@ -3916,11 +4173,11 @@
     // By checking the range of stream before calling getStrategy, we avoid
     // getStrategy's behavior for invalid streams.  getStrategy would do a ALOGE
     // and then return STRATEGY_MEDIA, but we want to return the empty set.
-    if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_CNT) {
+    if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_PUBLIC_CNT) {
         return AUDIO_DEVICE_NONE;
     }
     audio_devices_t devices;
-    AudioPolicyManager::routing_strategy strategy = getStrategy(stream);
+    routing_strategy strategy = getStrategy(stream);
     devices = getDeviceForStrategy(strategy, true /*fromCache*/);
     SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(devices, mOutputs);
     for (size_t i = 0; i < outputs.size(); i++) {
@@ -3941,8 +4198,11 @@
     return devices;
 }
 
-AudioPolicyManager::routing_strategy AudioPolicyManager::getStrategy(
+routing_strategy AudioPolicyManager::getStrategy(
         audio_stream_type_t stream) {
+
+    ALOG_ASSERT(stream != AUDIO_STREAM_PATCH,"getStrategy() called for AUDIO_STREAM_PATCH");
+
     // stream to strategy mapping
     switch (stream) {
     case AUDIO_STREAM_VOICE_CALL:
@@ -3956,7 +4216,7 @@
     case AUDIO_STREAM_DTMF:
         return STRATEGY_DTMF;
     default:
-        ALOGE("unknown stream type");
+        ALOGE("unknown stream type %d", stream);
     case AUDIO_STREAM_SYSTEM:
         // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
         // while key clicks are played produces a poor result
@@ -3966,6 +4226,10 @@
         return STRATEGY_ENFORCED_AUDIBLE;
     case AUDIO_STREAM_TTS:
         return STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
+    case AUDIO_STREAM_ACCESSIBILITY:
+        return STRATEGY_ACCESSIBILITY;
+    case AUDIO_STREAM_REROUTING:
+        return STRATEGY_REROUTING;
     }
 }
 
@@ -3980,9 +4244,17 @@
 
     // usage to strategy mapping
     switch (attr->usage) {
+    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+        if (isStreamActive(AUDIO_STREAM_RING) || isStreamActive(AUDIO_STREAM_ALARM)) {
+            return (uint32_t) STRATEGY_SONIFICATION;
+        }
+        if (isInCall()) {
+            return (uint32_t) STRATEGY_PHONE;
+        }
+        return (uint32_t) STRATEGY_ACCESSIBILITY;
+
     case AUDIO_USAGE_MEDIA:
     case AUDIO_USAGE_GAME:
-    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
     case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
         return (uint32_t) STRATEGY_MEDIA;
@@ -4153,7 +4425,8 @@
         //   - cannot route from voice call RX OR
         //   - audio HAL version is < 3.0 and TX device is on the primary HW module
         if (mPhoneState == AUDIO_MODE_IN_CALL) {
-            audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+            audio_devices_t txDevice =
+                    getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
             sp<AudioOutputDescriptor> hwOutputDesc = mOutputs.valueFor(mPrimaryOutput);
             if (((mAvailableInputDevices.types() &
                     AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) ||
@@ -4182,7 +4455,7 @@
             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
             if (!isInCall() &&
                     (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
-                    (getA2dpOutput() != 0) && !mA2dpSuspended) {
+                    (getA2dpOutput() != 0)) {
                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
                 if (device) break;
                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
@@ -4194,7 +4467,7 @@
             if (device) break;
             device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
             if (device) break;
-            if (mPhoneState != AUDIO_MODE_IN_CALL) {
+            if (!isInCall()) {
                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
                 if (device) break;
                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
@@ -4217,11 +4490,11 @@
             // A2DP speaker when forcing to speaker output
             if (!isInCall() &&
                     (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
-                    (getA2dpOutput() != 0) && !mA2dpSuspended) {
+                    (getA2dpOutput() != 0)) {
                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
                 if (device) break;
             }
-            if (mPhoneState != AUDIO_MODE_IN_CALL) {
+            if (!isInCall()) {
                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
                 if (device) break;
                 device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
@@ -4271,15 +4544,35 @@
         // The second device used for sonification is the same as the device used by media strategy
         // FALL THROUGH
 
+    // FIXME: STRATEGY_ACCESSIBILITY and STRATEGY_REROUTING follow STRATEGY_MEDIA for now
+    case STRATEGY_ACCESSIBILITY:
+        if (strategy == STRATEGY_ACCESSIBILITY) {
+            // do not route accessibility prompts to a digital output currently configured with a
+            // compressed format as they would likely not be mixed and dropped.
+            for (size_t i = 0; i < mOutputs.size(); i++) {
+                sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
+                audio_devices_t devices = desc->device() &
+                    (AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC);
+                if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) &&
+                        devices != AUDIO_DEVICE_NONE) {
+                    availableOutputDeviceTypes = availableOutputDeviceTypes & ~devices;
+                }
+            }
+        }
+        // FALL THROUGH
+
+    case STRATEGY_REROUTING:
     case STRATEGY_MEDIA: {
         uint32_t device2 = AUDIO_DEVICE_NONE;
         if (strategy != STRATEGY_SONIFICATION) {
             // no sonification on remote submix (e.g. WFD)
-            device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+            if (mAvailableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {
+                device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+            }
         }
         if ((device2 == AUDIO_DEVICE_NONE) &&
                 (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
-                (getA2dpOutput() != 0) && !mA2dpSuspended) {
+                (getA2dpOutput() != 0)) {
             device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
             if (device2 == AUDIO_DEVICE_NONE) {
                 device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
@@ -4684,7 +4977,8 @@
     return status;
 }
 
-sp<AudioPolicyManager::IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device,
+sp<IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device,
+                                                   String8 address,
                                                    uint32_t& samplingRate,
                                                    audio_format_t format,
                                                    audio_channel_mask_t channelMask,
@@ -4702,9 +4996,10 @@
         {
             sp<IOProfile> profile = mHwModules[i]->mInputProfiles[j];
             // profile->log();
-            if (profile->isCompatibleProfile(device, samplingRate,
+            if (profile->isCompatibleProfile(device, address, samplingRate,
                                              &samplingRate /*updatedSamplingRate*/,
                                              format, channelMask, (audio_output_flags_t) flags)) {
+
                 return profile;
             }
         }
@@ -4712,11 +5007,42 @@
     return NULL;
 }
 
+
+audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t inputSource,
+                                                            AudioMix **policyMix)
+{
+    audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
+                                            ~AUDIO_DEVICE_BIT_IN;
+
+    for (size_t i = 0; i < mPolicyMixes.size(); i++) {
+        if (mPolicyMixes[i]->mMix.mMixType != MIX_TYPE_RECORDERS) {
+            continue;
+        }
+        for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) {
+            if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
+                    mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource == inputSource) ||
+               (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
+                    mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource != inputSource)) {
+                if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+                    if (policyMix != NULL) {
+                        *policyMix = &mPolicyMixes[i]->mMix;
+                    }
+                    return AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+                }
+                break;
+            }
+        }
+    }
+
+    return getDeviceForInputSource(inputSource);
+}
+
 audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
 {
     uint32_t device = AUDIO_DEVICE_NONE;
     audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
                                             ~AUDIO_DEVICE_BIT_IN;
+
     switch (inputSource) {
     case AUDIO_SOURCE_VOICE_UPLINK:
       if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
@@ -4729,6 +5055,9 @@
     case AUDIO_SOURCE_MIC:
     if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
         device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
+    } else if ((mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO) &&
+        (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
+        device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
     } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
         device = AUDIO_DEVICE_IN_WIRED_HEADSET;
     } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
@@ -4830,7 +5159,7 @@
 }
 
 bool AudioPolicyManager::deviceDistinguishesOnAddress(audio_devices_t device) {
-    return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL) != 0);
+    return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0);
 }
 
 audio_io_handle_t AudioPolicyManager::getActiveInput(bool ignoreVirtualInputs)
@@ -4851,286 +5180,36 @@
     for (size_t i = 0; i < mInputs.size(); i++) {
         const sp<AudioInputDescriptor>  desc = mInputs.valueAt(i);
         if (desc->mRefCount > 0) {
-            return count++;
+            count++;
         }
     }
     return count;
 }
 
 
-audio_devices_t AudioPolicyManager::getDeviceForVolume(audio_devices_t device)
-{
-    if (device == AUDIO_DEVICE_NONE) {
-        // this happens when forcing a route update and no track is active on an output.
-        // In this case the returned category is not important.
-        device =  AUDIO_DEVICE_OUT_SPEAKER;
-    } else if (popcount(device) > 1) {
-        // Multiple device selection is either:
-        //  - speaker + one other device: give priority to speaker in this case.
-        //  - one A2DP device + another device: happens with duplicated output. In this case
-        // retain the device on the A2DP output as the other must not correspond to an active
-        // selection if not the speaker.
-        //  - HDMI-CEC system audio mode only output: give priority to available item in order.
-        if (device & AUDIO_DEVICE_OUT_SPEAKER) {
-            device = AUDIO_DEVICE_OUT_SPEAKER;
-        } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
-            device = AUDIO_DEVICE_OUT_HDMI_ARC;
-        } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
-            device = AUDIO_DEVICE_OUT_AUX_LINE;
-        } else if (device & AUDIO_DEVICE_OUT_SPDIF) {
-            device = AUDIO_DEVICE_OUT_SPDIF;
-        } else {
-            device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
-        }
-    }
-
-    /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
-    if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
-        device = AUDIO_DEVICE_OUT_SPEAKER;
-
-    ALOGW_IF(popcount(device) != 1,
-            "getDeviceForVolume() invalid device combination: %08x",
-            device);
-
-    return device;
-}
-
-AudioPolicyManager::device_category AudioPolicyManager::getDeviceCategory(audio_devices_t device)
-{
-    switch(getDeviceForVolume(device)) {
-        case AUDIO_DEVICE_OUT_EARPIECE:
-            return DEVICE_CATEGORY_EARPIECE;
-        case AUDIO_DEVICE_OUT_WIRED_HEADSET:
-        case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
-            return DEVICE_CATEGORY_HEADSET;
-        case AUDIO_DEVICE_OUT_LINE:
-        case AUDIO_DEVICE_OUT_AUX_DIGITAL:
-        /*USB?  Remote submix?*/
-            return DEVICE_CATEGORY_EXT_MEDIA;
-        case AUDIO_DEVICE_OUT_SPEAKER:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
-        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
-        case AUDIO_DEVICE_OUT_USB_ACCESSORY:
-        case AUDIO_DEVICE_OUT_USB_DEVICE:
-        case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
-        default:
-            return DEVICE_CATEGORY_SPEAKER;
-    }
-}
-
-float AudioPolicyManager::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
-        int indexInUi)
-{
-    device_category deviceCategory = getDeviceCategory(device);
-    const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory];
-
-    // the volume index in the UI is relative to the min and max volume indices for this stream type
-    int nbSteps = 1 + curve[VOLMAX].mIndex -
-            curve[VOLMIN].mIndex;
-    int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /
-            (streamDesc.mIndexMax - streamDesc.mIndexMin);
-
-    // find what part of the curve this index volume belongs to, or if it's out of bounds
-    int segment = 0;
-    if (volIdx < curve[VOLMIN].mIndex) {         // out of bounds
-        return 0.0f;
-    } else if (volIdx < curve[VOLKNEE1].mIndex) {
-        segment = 0;
-    } else if (volIdx < curve[VOLKNEE2].mIndex) {
-        segment = 1;
-    } else if (volIdx <= curve[VOLMAX].mIndex) {
-        segment = 2;
-    } else {                                                               // out of bounds
-        return 1.0f;
-    }
-
-    // linear interpolation in the attenuation table in dB
-    float decibels = curve[segment].mDBAttenuation +
-            ((float)(volIdx - curve[segment].mIndex)) *
-                ( (curve[segment+1].mDBAttenuation -
-                        curve[segment].mDBAttenuation) /
-                    ((float)(curve[segment+1].mIndex -
-                            curve[segment].mIndex)) );
-
-    float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )
-
-    ALOGVV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f",
-            curve[segment].mIndex, volIdx,
-            curve[segment+1].mIndex,
-            curve[segment].mDBAttenuation,
-            decibels,
-            curve[segment+1].mDBAttenuation,
-            amplification);
-
-    return amplification;
-}
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sDefaultVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sDefaultMediaVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sExtMediaSystemVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sSpeakerMediaVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sSpeakerMediaVolumeCurveDrc[AudioPolicyManager::VOLCNT] = {
-    {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sSpeakerSonificationVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sSpeakerSonificationVolumeCurveDrc[AudioPolicyManager::VOLCNT] = {
-    {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f}
-};
-
-// AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks
-// AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets.
-// AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java).
-// The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset.
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sDefaultSystemVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sDefaultSystemVolumeCurveDrc[AudioPolicyManager::VOLCNT] = {
-    {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sHeadsetSystemVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sDefaultVoiceVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sSpeakerVoiceVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sLinearVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-    AudioPolicyManager::sSilentVolumeCurve[AudioPolicyManager::VOLCNT] = {
-    {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f}
-};
-
-const AudioPolicyManager::VolumeCurvePoint
-            *AudioPolicyManager::sVolumeProfiles[AUDIO_STREAM_CNT]
-                                                   [AudioPolicyManager::DEVICE_CATEGORY_CNT] = {
-    { // AUDIO_STREAM_VOICE_CALL
-        sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_SYSTEM
-        sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        sDefaultSystemVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
-        sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_RING
-        sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
-        sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_MUSIC
-        sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_ALARM
-        sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
-        sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_NOTIFICATION
-        sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
-        sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_BLUETOOTH_SCO
-        sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_ENFORCED_AUDIBLE
-        sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    {  // AUDIO_STREAM_DTMF
-        sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-    { // AUDIO_STREAM_TTS
-      // "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER
-        sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET
-        sLinearVolumeCurve, // DEVICE_CATEGORY_SPEAKER
-        sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE
-        sSilentVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
-    },
-};
-
 void AudioPolicyManager::initializeVolumeCurves()
 {
     for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
-        for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
+        for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) {
             mStreams[i].mVolumeCurve[j] =
-                    sVolumeProfiles[i][j];
+                    ApmGains::sVolumeProfiles[i][j];
         }
     }
 
     // Check availability of DRC on speaker path: if available, override some of the speaker curves
     if (mSpeakerDrcEnabled) {
-        mStreams[AUDIO_STREAM_SYSTEM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] =
-                sDefaultSystemVolumeCurveDrc;
-        mStreams[AUDIO_STREAM_RING].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] =
-                sSpeakerSonificationVolumeCurveDrc;
-        mStreams[AUDIO_STREAM_ALARM].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] =
-                sSpeakerSonificationVolumeCurveDrc;
-        mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] =
-                sSpeakerSonificationVolumeCurveDrc;
-        mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[DEVICE_CATEGORY_SPEAKER] =
-                sSpeakerMediaVolumeCurveDrc;
+        mStreams[AUDIO_STREAM_SYSTEM].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
+                ApmGains::sDefaultSystemVolumeCurveDrc;
+        mStreams[AUDIO_STREAM_RING].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
+                ApmGains::sSpeakerSonificationVolumeCurveDrc;
+        mStreams[AUDIO_STREAM_ALARM].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
+                ApmGains::sSpeakerSonificationVolumeCurveDrc;
+        mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
+                ApmGains::sSpeakerSonificationVolumeCurveDrc;
+        mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
+                ApmGains::sSpeakerMediaVolumeCurveDrc;
+        mStreams[AUDIO_STREAM_ACCESSIBILITY].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
+                ApmGains::sSpeakerMediaVolumeCurveDrc;
     }
 }
 
@@ -5147,7 +5226,7 @@
         device = outputDesc->device();
     }
 
-    volume = volIndexToAmpl(device, streamDesc, index);
+    volume = ApmGains::volIndexToAmpl(device, streamDesc, index);
 
     // if a headset is connected, apply the following rules to ring tones and notifications
     // to avoid sound level bursts in user's ears:
@@ -5214,6 +5293,18 @@
     }
 
     float volume = computeVolume(stream, index, output, device);
+    // unit gain if rerouting to external policy
+    if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
+        ssize_t index = mOutputs.indexOfKey(output);
+        if (index >= 0) {
+            sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index);
+            if (outputDesc->mPolicyMix != NULL) {
+                ALOGV("max gain when rerouting for output=%d", output);
+                volume = 1.0f;
+            }
+        }
+
+    }
     // We actually change the volume if:
     // - the float value returned by computeVolume() changed
     // - the force flag is set
@@ -5256,6 +5347,9 @@
     ALOGVV("applyStreamVolumes() for output %d and device %x", output, device);
 
     for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
+        if (stream == AUDIO_STREAM_PATCH) {
+            continue;
+        }
         checkAndSetVolume((audio_stream_type_t)stream,
                           mStreams[stream].getVolumeIndex(device),
                           output,
@@ -5273,6 +5367,9 @@
 {
     ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
     for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
+        if (stream == AUDIO_STREAM_PATCH) {
+            continue;
+        }
         if (getStrategy((audio_stream_type_t)stream) == strategy) {
             setStreamMute((audio_stream_type_t)stream, on, output, delayMs, device);
         }
@@ -5385,315 +5482,6 @@
 }
 
 
-// --- AudioOutputDescriptor class implementation
-
-AudioPolicyManager::AudioOutputDescriptor::AudioOutputDescriptor(
-        const sp<IOProfile>& profile)
-    : mId(0), mIoHandle(0), mLatency(0),
-    mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPatchHandle(0),
-    mOutput1(0), mOutput2(0), mProfile(profile), mDirectOpenCount(0)
-{
-    // clear usage count for all stream types
-    for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
-        mRefCount[i] = 0;
-        mCurVolume[i] = -1.0;
-        mMuteCount[i] = 0;
-        mStopTime[i] = 0;
-    }
-    for (int i = 0; i < NUM_STRATEGIES; i++) {
-        mStrategyMutedByDevice[i] = false;
-    }
-    if (profile != NULL) {
-        mFlags = (audio_output_flags_t)profile->mFlags;
-        mSamplingRate = profile->pickSamplingRate();
-        mFormat = profile->pickFormat();
-        mChannelMask = profile->pickChannelMask();
-        if (profile->mGains.size() > 0) {
-            profile->mGains[0]->getDefaultConfig(&mGain);
-        }
-    }
-}
-
-audio_devices_t AudioPolicyManager::AudioOutputDescriptor::device() const
-{
-    if (isDuplicated()) {
-        return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice);
-    } else {
-        return mDevice;
-    }
-}
-
-uint32_t AudioPolicyManager::AudioOutputDescriptor::latency()
-{
-    if (isDuplicated()) {
-        return (mOutput1->mLatency > mOutput2->mLatency) ? mOutput1->mLatency : mOutput2->mLatency;
-    } else {
-        return mLatency;
-    }
-}
-
-bool AudioPolicyManager::AudioOutputDescriptor::sharesHwModuleWith(
-        const sp<AudioOutputDescriptor> outputDesc)
-{
-    if (isDuplicated()) {
-        return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc);
-    } else if (outputDesc->isDuplicated()){
-        return sharesHwModuleWith(outputDesc->mOutput1) || sharesHwModuleWith(outputDesc->mOutput2);
-    } else {
-        return (mProfile->mModule == outputDesc->mProfile->mModule);
-    }
-}
-
-void AudioPolicyManager::AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream,
-                                                                   int delta)
-{
-    // forward usage count change to attached outputs
-    if (isDuplicated()) {
-        mOutput1->changeRefCount(stream, delta);
-        mOutput2->changeRefCount(stream, delta);
-    }
-    if ((delta + (int)mRefCount[stream]) < 0) {
-        ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d",
-              delta, stream, mRefCount[stream]);
-        mRefCount[stream] = 0;
-        return;
-    }
-    mRefCount[stream] += delta;
-    ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
-}
-
-audio_devices_t AudioPolicyManager::AudioOutputDescriptor::supportedDevices()
-{
-    if (isDuplicated()) {
-        return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices());
-    } else {
-        return mProfile->mSupportedDevices.types() ;
-    }
-}
-
-bool AudioPolicyManager::AudioOutputDescriptor::isActive(uint32_t inPastMs) const
-{
-    return isStrategyActive(NUM_STRATEGIES, inPastMs);
-}
-
-bool AudioPolicyManager::AudioOutputDescriptor::isStrategyActive(routing_strategy strategy,
-                                                                       uint32_t inPastMs,
-                                                                       nsecs_t sysTime) const
-{
-    if ((sysTime == 0) && (inPastMs != 0)) {
-        sysTime = systemTime();
-    }
-    for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
-        if (((getStrategy((audio_stream_type_t)i) == strategy) ||
-                (NUM_STRATEGIES == strategy)) &&
-                isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool AudioPolicyManager::AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream,
-                                                                       uint32_t inPastMs,
-                                                                       nsecs_t sysTime) const
-{
-    if (mRefCount[stream] != 0) {
-        return true;
-    }
-    if (inPastMs == 0) {
-        return false;
-    }
-    if (sysTime == 0) {
-        sysTime = systemTime();
-    }
-    if (ns2ms(sysTime - mStopTime[stream]) < inPastMs) {
-        return true;
-    }
-    return false;
-}
-
-void AudioPolicyManager::AudioOutputDescriptor::toAudioPortConfig(
-                                                 struct audio_port_config *dstConfig,
-                                                 const struct audio_port_config *srcConfig) const
-{
-    ALOG_ASSERT(!isDuplicated(), "toAudioPortConfig() called on duplicated output %d", mIoHandle);
-
-    dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
-                            AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
-    if (srcConfig != NULL) {
-        dstConfig->config_mask |= srcConfig->config_mask;
-    }
-    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
-
-    dstConfig->id = mId;
-    dstConfig->role = AUDIO_PORT_ROLE_SOURCE;
-    dstConfig->type = AUDIO_PORT_TYPE_MIX;
-    dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle;
-    dstConfig->ext.mix.handle = mIoHandle;
-    dstConfig->ext.mix.usecase.stream = AUDIO_STREAM_DEFAULT;
-}
-
-void AudioPolicyManager::AudioOutputDescriptor::toAudioPort(
-                                                    struct audio_port *port) const
-{
-    ALOG_ASSERT(!isDuplicated(), "toAudioPort() called on duplicated output %d", mIoHandle);
-    mProfile->toAudioPort(port);
-    port->id = mId;
-    toAudioPortConfig(&port->active_config);
-    port->ext.mix.hw_module = mProfile->mModule->mHandle;
-    port->ext.mix.handle = mIoHandle;
-    port->ext.mix.latency_class =
-            mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL;
-}
-
-status_t AudioPolicyManager::AudioOutputDescriptor::dump(int fd)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, " ID: %d\n", mId);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Format: %08x\n", mFormat);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Devices %08x\n", device());
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Stream volume refCount muteCount\n");
-    result.append(buffer);
-    for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
-        snprintf(buffer, SIZE, " %02d     %.03f     %02d       %02d\n",
-                 i, mCurVolume[i], mRefCount[i], mMuteCount[i]);
-        result.append(buffer);
-    }
-    write(fd, result.string(), result.size());
-
-    return NO_ERROR;
-}
-
-// --- AudioInputDescriptor class implementation
-
-AudioPolicyManager::AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile)
-    : mId(0), mIoHandle(0),
-      mDevice(AUDIO_DEVICE_NONE), mPatchHandle(0), mRefCount(0),
-      mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile), mIsSoundTrigger(false)
-{
-    if (profile != NULL) {
-        mSamplingRate = profile->pickSamplingRate();
-        mFormat = profile->pickFormat();
-        mChannelMask = profile->pickChannelMask();
-        if (profile->mGains.size() > 0) {
-            profile->mGains[0]->getDefaultConfig(&mGain);
-        }
-    }
-}
-
-void AudioPolicyManager::AudioInputDescriptor::toAudioPortConfig(
-                                                   struct audio_port_config *dstConfig,
-                                                   const struct audio_port_config *srcConfig) const
-{
-    ALOG_ASSERT(mProfile != 0,
-                "toAudioPortConfig() called on input with null profile %d", mIoHandle);
-    dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
-                            AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
-    if (srcConfig != NULL) {
-        dstConfig->config_mask |= srcConfig->config_mask;
-    }
-
-    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
-
-    dstConfig->id = mId;
-    dstConfig->role = AUDIO_PORT_ROLE_SINK;
-    dstConfig->type = AUDIO_PORT_TYPE_MIX;
-    dstConfig->ext.mix.hw_module = mProfile->mModule->mHandle;
-    dstConfig->ext.mix.handle = mIoHandle;
-    dstConfig->ext.mix.usecase.source = mInputSource;
-}
-
-void AudioPolicyManager::AudioInputDescriptor::toAudioPort(
-                                                    struct audio_port *port) const
-{
-    ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle);
-
-    mProfile->toAudioPort(port);
-    port->id = mId;
-    toAudioPortConfig(&port->active_config);
-    port->ext.mix.hw_module = mProfile->mModule->mHandle;
-    port->ext.mix.handle = mIoHandle;
-    port->ext.mix.latency_class = AUDIO_LATENCY_NORMAL;
-}
-
-status_t AudioPolicyManager::AudioInputDescriptor::dump(int fd)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, " ID: %d\n", mId);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
-    result.append(buffer);
-    snprintf(buffer, SIZE, " Open Ref Count %d\n", mOpenRefCount);
-    result.append(buffer);
-
-    write(fd, result.string(), result.size());
-
-    return NO_ERROR;
-}
-
-// --- StreamDescriptor class implementation
-
-AudioPolicyManager::StreamDescriptor::StreamDescriptor()
-    :   mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
-{
-    mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
-}
-
-int AudioPolicyManager::StreamDescriptor::getVolumeIndex(audio_devices_t device)
-{
-    device = AudioPolicyManager::getDeviceForVolume(device);
-    // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
-    if (mIndexCur.indexOfKey(device) < 0) {
-        device = AUDIO_DEVICE_OUT_DEFAULT;
-    }
-    return mIndexCur.valueFor(device);
-}
-
-void AudioPolicyManager::StreamDescriptor::dump(int fd)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, "%s         %02d         %02d         ",
-             mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
-    result.append(buffer);
-    for (size_t i = 0; i < mIndexCur.size(); i++) {
-        snprintf(buffer, SIZE, "%04x : %02d, ",
-                 mIndexCur.keyAt(i),
-                 mIndexCur.valueAt(i));
-        result.append(buffer);
-    }
-    result.append("\n");
-
-    write(fd, result.string(), result.size());
-}
-
 // --- EffectDescriptor class implementation
 
 status_t AudioPolicyManager::EffectDescriptor::dump(int fd)
@@ -5717,1512 +5505,9 @@
     return NO_ERROR;
 }
 
-// --- HwModule class implementation
-
-AudioPolicyManager::HwModule::HwModule(const char *name)
-    : mName(strndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN)),
-      mHalVersion(AUDIO_DEVICE_API_VERSION_MIN), mHandle(0)
-{
-}
-
-AudioPolicyManager::HwModule::~HwModule()
-{
-    for (size_t i = 0; i < mOutputProfiles.size(); i++) {
-        mOutputProfiles[i]->mSupportedDevices.clear();
-    }
-    for (size_t i = 0; i < mInputProfiles.size(); i++) {
-        mInputProfiles[i]->mSupportedDevices.clear();
-    }
-    free((void *)mName);
-}
-
-status_t AudioPolicyManager::HwModule::loadInput(cnode *root)
-{
-    cnode *node = root->first_child;
-
-    sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK, this);
-
-    while (node) {
-        if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
-            profile->loadSamplingRates((char *)node->value);
-        } else if (strcmp(node->name, FORMATS_TAG) == 0) {
-            profile->loadFormats((char *)node->value);
-        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
-            profile->loadInChannels((char *)node->value);
-        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
-            profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
-                                                           mDeclaredDevices);
-        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
-            profile->mFlags = parseInputFlagNames((char *)node->value);
-        } else if (strcmp(node->name, GAINS_TAG) == 0) {
-            profile->loadGains(node);
-        }
-        node = node->next;
-    }
-    ALOGW_IF(profile->mSupportedDevices.isEmpty(),
-            "loadInput() invalid supported devices");
-    ALOGW_IF(profile->mChannelMasks.size() == 0,
-            "loadInput() invalid supported channel masks");
-    ALOGW_IF(profile->mSamplingRates.size() == 0,
-            "loadInput() invalid supported sampling rates");
-    ALOGW_IF(profile->mFormats.size() == 0,
-            "loadInput() invalid supported formats");
-    if (!profile->mSupportedDevices.isEmpty() &&
-            (profile->mChannelMasks.size() != 0) &&
-            (profile->mSamplingRates.size() != 0) &&
-            (profile->mFormats.size() != 0)) {
-
-        ALOGV("loadInput() adding input Supported Devices %04x",
-              profile->mSupportedDevices.types());
-
-        mInputProfiles.add(profile);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioPolicyManager::HwModule::loadOutput(cnode *root)
-{
-    cnode *node = root->first_child;
-
-    sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE, this);
-
-    while (node) {
-        if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
-            profile->loadSamplingRates((char *)node->value);
-        } else if (strcmp(node->name, FORMATS_TAG) == 0) {
-            profile->loadFormats((char *)node->value);
-        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
-            profile->loadOutChannels((char *)node->value);
-        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
-            profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
-                                                           mDeclaredDevices);
-        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
-            profile->mFlags = parseOutputFlagNames((char *)node->value);
-        } else if (strcmp(node->name, GAINS_TAG) == 0) {
-            profile->loadGains(node);
-        }
-        node = node->next;
-    }
-    ALOGW_IF(profile->mSupportedDevices.isEmpty(),
-            "loadOutput() invalid supported devices");
-    ALOGW_IF(profile->mChannelMasks.size() == 0,
-            "loadOutput() invalid supported channel masks");
-    ALOGW_IF(profile->mSamplingRates.size() == 0,
-            "loadOutput() invalid supported sampling rates");
-    ALOGW_IF(profile->mFormats.size() == 0,
-            "loadOutput() invalid supported formats");
-    if (!profile->mSupportedDevices.isEmpty() &&
-            (profile->mChannelMasks.size() != 0) &&
-            (profile->mSamplingRates.size() != 0) &&
-            (profile->mFormats.size() != 0)) {
-
-        ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x",
-              profile->mSupportedDevices.types(), profile->mFlags);
-
-        mOutputProfiles.add(profile);
-        return NO_ERROR;
-    } else {
-        return BAD_VALUE;
-    }
-}
-
-status_t AudioPolicyManager::HwModule::loadDevice(cnode *root)
-{
-    cnode *node = root->first_child;
-
-    audio_devices_t type = AUDIO_DEVICE_NONE;
-    while (node) {
-        if (strcmp(node->name, DEVICE_TYPE) == 0) {
-            type = parseDeviceNames((char *)node->value);
-            break;
-        }
-        node = node->next;
-    }
-    if (type == AUDIO_DEVICE_NONE ||
-            (!audio_is_input_device(type) && !audio_is_output_device(type))) {
-        ALOGW("loadDevice() bad type %08x", type);
-        return BAD_VALUE;
-    }
-    sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(String8(root->name), type);
-    deviceDesc->mModule = this;
-
-    node = root->first_child;
-    while (node) {
-        if (strcmp(node->name, DEVICE_ADDRESS) == 0) {
-            deviceDesc->mAddress = String8((char *)node->value);
-        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
-            if (audio_is_input_device(type)) {
-                deviceDesc->loadInChannels((char *)node->value);
-            } else {
-                deviceDesc->loadOutChannels((char *)node->value);
-            }
-        } else if (strcmp(node->name, GAINS_TAG) == 0) {
-            deviceDesc->loadGains(node);
-        }
-        node = node->next;
-    }
-
-    ALOGV("loadDevice() adding device name %s type %08x address %s",
-          deviceDesc->mName.string(), type, deviceDesc->mAddress.string());
-
-    mDeclaredDevices.add(deviceDesc);
-
-    return NO_ERROR;
-}
-
-void AudioPolicyManager::HwModule::dump(int fd)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, "  - name: %s\n", mName);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "  - handle: %d\n", mHandle);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "  - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF);
-    result.append(buffer);
-    write(fd, result.string(), result.size());
-    if (mOutputProfiles.size()) {
-        write(fd, "  - outputs:\n", strlen("  - outputs:\n"));
-        for (size_t i = 0; i < mOutputProfiles.size(); i++) {
-            snprintf(buffer, SIZE, "    output %zu:\n", i);
-            write(fd, buffer, strlen(buffer));
-            mOutputProfiles[i]->dump(fd);
-        }
-    }
-    if (mInputProfiles.size()) {
-        write(fd, "  - inputs:\n", strlen("  - inputs:\n"));
-        for (size_t i = 0; i < mInputProfiles.size(); i++) {
-            snprintf(buffer, SIZE, "    input %zu:\n", i);
-            write(fd, buffer, strlen(buffer));
-            mInputProfiles[i]->dump(fd);
-        }
-    }
-    if (mDeclaredDevices.size()) {
-        write(fd, "  - devices:\n", strlen("  - devices:\n"));
-        for (size_t i = 0; i < mDeclaredDevices.size(); i++) {
-            mDeclaredDevices[i]->dump(fd, 4, i);
-        }
-    }
-}
-
-// --- AudioPort class implementation
-
-
-AudioPolicyManager::AudioPort::AudioPort(const String8& name, audio_port_type_t type,
-          audio_port_role_t role, const sp<HwModule>& module) :
-    mName(name), mType(type), mRole(role), mModule(module), mFlags(0)
-{
-    mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
-                    ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
-}
-
-void AudioPolicyManager::AudioPort::toAudioPort(struct audio_port *port) const
-{
-    port->role = mRole;
-    port->type = mType;
-    unsigned int i;
-    for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) {
-        if (mSamplingRates[i] != 0) {
-            port->sample_rates[i] = mSamplingRates[i];
-        }
-    }
-    port->num_sample_rates = i;
-    for (i = 0; i < mChannelMasks.size() && i < AUDIO_PORT_MAX_CHANNEL_MASKS; i++) {
-        if (mChannelMasks[i] != 0) {
-            port->channel_masks[i] = mChannelMasks[i];
-        }
-    }
-    port->num_channel_masks = i;
-    for (i = 0; i < mFormats.size() && i < AUDIO_PORT_MAX_FORMATS; i++) {
-        if (mFormats[i] != 0) {
-            port->formats[i] = mFormats[i];
-        }
-    }
-    port->num_formats = i;
-
-    ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
-
-    for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
-        port->gains[i] = mGains[i]->mGain;
-    }
-    port->num_gains = i;
-}
-
-void AudioPolicyManager::AudioPort::importAudioPort(const sp<AudioPort> port) {
-    for (size_t k = 0 ; k < port->mSamplingRates.size() ; k++) {
-        const uint32_t rate = port->mSamplingRates.itemAt(k);
-        if (rate != 0) { // skip "dynamic" rates
-            bool hasRate = false;
-            for (size_t l = 0 ; l < mSamplingRates.size() ; l++) {
-                if (rate == mSamplingRates.itemAt(l)) {
-                    hasRate = true;
-                    break;
-                }
-            }
-            if (!hasRate) { // never import a sampling rate twice
-                mSamplingRates.add(rate);
-            }
-        }
-    }
-    for (size_t k = 0 ; k < port->mChannelMasks.size() ; k++) {
-        const audio_channel_mask_t mask = port->mChannelMasks.itemAt(k);
-        if (mask != 0) { // skip "dynamic" masks
-            bool hasMask = false;
-            for (size_t l = 0 ; l < mChannelMasks.size() ; l++) {
-                if (mask == mChannelMasks.itemAt(l)) {
-                    hasMask = true;
-                    break;
-                }
-            }
-            if (!hasMask) { // never import a channel mask twice
-                mChannelMasks.add(mask);
-            }
-        }
-    }
-    for (size_t k = 0 ; k < port->mFormats.size() ; k++) {
-        const audio_format_t format = port->mFormats.itemAt(k);
-        if (format != 0) { // skip "dynamic" formats
-            bool hasFormat = false;
-            for (size_t l = 0 ; l < mFormats.size() ; l++) {
-                if (format == mFormats.itemAt(l)) {
-                    hasFormat = true;
-                    break;
-                }
-            }
-            if (!hasFormat) { // never import a channel mask twice
-                mFormats.add(format);
-            }
-        }
-    }
-    for (size_t k = 0 ; k < port->mGains.size() ; k++) {
-        sp<AudioGain> gain = port->mGains.itemAt(k);
-        if (gain != 0) {
-            bool hasGain = false;
-            for (size_t l = 0 ; l < mGains.size() ; l++) {
-                if (gain == mGains.itemAt(l)) {
-                    hasGain = true;
-                    break;
-                }
-            }
-            if (!hasGain) { // never import a gain twice
-                mGains.add(gain);
-            }
-        }
-    }
-}
-
-void AudioPolicyManager::AudioPort::clearCapabilities() {
-    mChannelMasks.clear();
-    mFormats.clear();
-    mSamplingRates.clear();
-    mGains.clear();
-}
-
-void AudioPolicyManager::AudioPort::loadSamplingRates(char *name)
-{
-    char *str = strtok(name, "|");
-
-    // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling
-    // rates should be read from the output stream after it is opened for the first time
-    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
-        mSamplingRates.add(0);
-        return;
-    }
-
-    while (str != NULL) {
-        uint32_t rate = atoi(str);
-        if (rate != 0) {
-            ALOGV("loadSamplingRates() adding rate %d", rate);
-            mSamplingRates.add(rate);
-        }
-        str = strtok(NULL, "|");
-    }
-}
-
-void AudioPolicyManager::AudioPort::loadFormats(char *name)
-{
-    char *str = strtok(name, "|");
-
-    // by convention, "0' in the first entry in mFormats indicates the supported formats
-    // should be read from the output stream after it is opened for the first time
-    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
-        mFormats.add(AUDIO_FORMAT_DEFAULT);
-        return;
-    }
-
-    while (str != NULL) {
-        audio_format_t format = (audio_format_t)stringToEnum(sFormatNameToEnumTable,
-                                                             ARRAY_SIZE(sFormatNameToEnumTable),
-                                                             str);
-        if (format != AUDIO_FORMAT_DEFAULT) {
-            mFormats.add(format);
-        }
-        str = strtok(NULL, "|");
-    }
-}
-
-void AudioPolicyManager::AudioPort::loadInChannels(char *name)
-{
-    const char *str = strtok(name, "|");
-
-    ALOGV("loadInChannels() %s", name);
-
-    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
-        mChannelMasks.add(0);
-        return;
-    }
-
-    while (str != NULL) {
-        audio_channel_mask_t channelMask =
-                (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable,
-                                                   ARRAY_SIZE(sInChannelsNameToEnumTable),
-                                                   str);
-        if (channelMask != 0) {
-            ALOGV("loadInChannels() adding channelMask %04x", channelMask);
-            mChannelMasks.add(channelMask);
-        }
-        str = strtok(NULL, "|");
-    }
-}
-
-void AudioPolicyManager::AudioPort::loadOutChannels(char *name)
-{
-    const char *str = strtok(name, "|");
-
-    ALOGV("loadOutChannels() %s", name);
-
-    // by convention, "0' in the first entry in mChannelMasks indicates the supported channel
-    // masks should be read from the output stream after it is opened for the first time
-    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
-        mChannelMasks.add(0);
-        return;
-    }
-
-    while (str != NULL) {
-        audio_channel_mask_t channelMask =
-                (audio_channel_mask_t)stringToEnum(sOutChannelsNameToEnumTable,
-                                                   ARRAY_SIZE(sOutChannelsNameToEnumTable),
-                                                   str);
-        if (channelMask != 0) {
-            mChannelMasks.add(channelMask);
-        }
-        str = strtok(NULL, "|");
-    }
-    return;
-}
-
-audio_gain_mode_t AudioPolicyManager::AudioPort::loadGainMode(char *name)
-{
-    const char *str = strtok(name, "|");
-
-    ALOGV("loadGainMode() %s", name);
-    audio_gain_mode_t mode = 0;
-    while (str != NULL) {
-        mode |= (audio_gain_mode_t)stringToEnum(sGainModeNameToEnumTable,
-                                                ARRAY_SIZE(sGainModeNameToEnumTable),
-                                                str);
-        str = strtok(NULL, "|");
-    }
-    return mode;
-}
-
-void AudioPolicyManager::AudioPort::loadGain(cnode *root, int index)
-{
-    cnode *node = root->first_child;
-
-    sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask);
-
-    while (node) {
-        if (strcmp(node->name, GAIN_MODE) == 0) {
-            gain->mGain.mode = loadGainMode((char *)node->value);
-        } else if (strcmp(node->name, GAIN_CHANNELS) == 0) {
-            if (mUseInChannelMask) {
-                gain->mGain.channel_mask =
-                        (audio_channel_mask_t)stringToEnum(sInChannelsNameToEnumTable,
-                                                           ARRAY_SIZE(sInChannelsNameToEnumTable),
-                                                           (char *)node->value);
-            } else {
-                gain->mGain.channel_mask =
-                        (audio_channel_mask_t)stringToEnum(sOutChannelsNameToEnumTable,
-                                                           ARRAY_SIZE(sOutChannelsNameToEnumTable),
-                                                           (char *)node->value);
-            }
-        } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) {
-            gain->mGain.min_value = atoi((char *)node->value);
-        } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) {
-            gain->mGain.max_value = atoi((char *)node->value);
-        } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) {
-            gain->mGain.default_value = atoi((char *)node->value);
-        } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) {
-            gain->mGain.step_value = atoi((char *)node->value);
-        } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) {
-            gain->mGain.min_ramp_ms = atoi((char *)node->value);
-        } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) {
-            gain->mGain.max_ramp_ms = atoi((char *)node->value);
-        }
-        node = node->next;
-    }
-
-    ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d",
-          gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value);
-
-    if (gain->mGain.mode == 0) {
-        return;
-    }
-    mGains.add(gain);
-}
-
-void AudioPolicyManager::AudioPort::loadGains(cnode *root)
-{
-    cnode *node = root->first_child;
-    int index = 0;
-    while (node) {
-        ALOGV("loadGains() loading gain %s", node->name);
-        loadGain(node, index++);
-        node = node->next;
-    }
-}
-
-status_t AudioPolicyManager::AudioPort::checkExactSamplingRate(uint32_t samplingRate) const
-{
-    for (size_t i = 0; i < mSamplingRates.size(); i ++) {
-        if (mSamplingRates[i] == samplingRate) {
-            return NO_ERROR;
-        }
-    }
-    return BAD_VALUE;
-}
-
-status_t AudioPolicyManager::AudioPort::checkCompatibleSamplingRate(uint32_t samplingRate,
-        uint32_t *updatedSamplingRate) const
-{
-    // Search for the closest supported sampling rate that is above (preferred)
-    // or below (acceptable) the desired sampling rate, within a permitted ratio.
-    // The sampling rates do not need to be sorted in ascending order.
-    ssize_t maxBelow = -1;
-    ssize_t minAbove = -1;
-    uint32_t candidate;
-    for (size_t i = 0; i < mSamplingRates.size(); i++) {
-        candidate = mSamplingRates[i];
-        if (candidate == samplingRate) {
-            if (updatedSamplingRate != NULL) {
-                *updatedSamplingRate = candidate;
-            }
-            return NO_ERROR;
-        }
-        // candidate < desired
-        if (candidate < samplingRate) {
-            if (maxBelow < 0 || candidate > mSamplingRates[maxBelow]) {
-                maxBelow = i;
-            }
-        // candidate > desired
-        } else {
-            if (minAbove < 0 || candidate < mSamplingRates[minAbove]) {
-                minAbove = i;
-            }
-        }
-    }
-    // This uses hard-coded knowledge about AudioFlinger resampling ratios.
-    // TODO Move these assumptions out.
-    static const uint32_t kMaxDownSampleRatio = 6;  // beyond this aliasing occurs
-    static const uint32_t kMaxUpSampleRatio = 256;  // beyond this sample rate inaccuracies occur
-                                                    // due to approximation by an int32_t of the
-                                                    // phase increments
-    // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
-    if (minAbove >= 0) {
-        candidate = mSamplingRates[minAbove];
-        if (candidate / kMaxDownSampleRatio <= samplingRate) {
-            if (updatedSamplingRate != NULL) {
-                *updatedSamplingRate = candidate;
-            }
-            return NO_ERROR;
-        }
-    }
-    // But if we have to up-sample from a lower sampling rate, that's OK.
-    if (maxBelow >= 0) {
-        candidate = mSamplingRates[maxBelow];
-        if (candidate * kMaxUpSampleRatio >= samplingRate) {
-            if (updatedSamplingRate != NULL) {
-                *updatedSamplingRate = candidate;
-            }
-            return NO_ERROR;
-        }
-    }
-    // leave updatedSamplingRate unmodified
-    return BAD_VALUE;
-}
-
-status_t AudioPolicyManager::AudioPort::checkExactChannelMask(audio_channel_mask_t channelMask) const
-{
-    for (size_t i = 0; i < mChannelMasks.size(); i++) {
-        if (mChannelMasks[i] == channelMask) {
-            return NO_ERROR;
-        }
-    }
-    return BAD_VALUE;
-}
-
-status_t AudioPolicyManager::AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask)
-        const
-{
-    const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
-    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
-        // FIXME Does not handle multi-channel automatic conversions yet
-        audio_channel_mask_t supported = mChannelMasks[i];
-        if (supported == channelMask) {
-            return NO_ERROR;
-        }
-        if (isRecordThread) {
-            // This uses hard-coded knowledge that AudioFlinger can silently down-mix and up-mix.
-            // FIXME Abstract this out to a table.
-            if (((supported == AUDIO_CHANNEL_IN_FRONT_BACK || supported == AUDIO_CHANNEL_IN_STEREO)
-                    && channelMask == AUDIO_CHANNEL_IN_MONO) ||
-                (supported == AUDIO_CHANNEL_IN_MONO && (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK
-                    || channelMask == AUDIO_CHANNEL_IN_STEREO))) {
-                return NO_ERROR;
-            }
-        }
-    }
-    return BAD_VALUE;
-}
-
-status_t AudioPolicyManager::AudioPort::checkFormat(audio_format_t format) const
-{
-    for (size_t i = 0; i < mFormats.size(); i ++) {
-        if (mFormats[i] == format) {
-            return NO_ERROR;
-        }
-    }
-    return BAD_VALUE;
-}
-
-
-uint32_t AudioPolicyManager::AudioPort::pickSamplingRate() const
-{
-    // special case for uninitialized dynamic profile
-    if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) {
-        return 0;
-    }
-
-    // For direct outputs, pick minimum sampling rate: this helps ensuring that the
-    // channel count / sampling rate combination chosen will be supported by the connected
-    // sink
-    if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
-            (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) {
-        uint32_t samplingRate = UINT_MAX;
-        for (size_t i = 0; i < mSamplingRates.size(); i ++) {
-            if ((mSamplingRates[i] < samplingRate) && (mSamplingRates[i] > 0)) {
-                samplingRate = mSamplingRates[i];
-            }
-        }
-        return (samplingRate == UINT_MAX) ? 0 : samplingRate;
-    }
-
-    uint32_t samplingRate = 0;
-    uint32_t maxRate = MAX_MIXER_SAMPLING_RATE;
-
-    // For mixed output and inputs, use max mixer sampling rates. Do not
-    // limit sampling rate otherwise
-    if (mType != AUDIO_PORT_TYPE_MIX) {
-        maxRate = UINT_MAX;
-    }
-    for (size_t i = 0; i < mSamplingRates.size(); i ++) {
-        if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) {
-            samplingRate = mSamplingRates[i];
-        }
-    }
-    return samplingRate;
-}
-
-audio_channel_mask_t AudioPolicyManager::AudioPort::pickChannelMask() const
-{
-    // special case for uninitialized dynamic profile
-    if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) {
-        return AUDIO_CHANNEL_NONE;
-    }
-    audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE;
-
-    // For direct outputs, pick minimum channel count: this helps ensuring that the
-    // channel count / sampling rate combination chosen will be supported by the connected
-    // sink
-    if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
-            (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) {
-        uint32_t channelCount = UINT_MAX;
-        for (size_t i = 0; i < mChannelMasks.size(); i ++) {
-            uint32_t cnlCount;
-            if (mUseInChannelMask) {
-                cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
-            } else {
-                cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
-            }
-            if ((cnlCount < channelCount) && (cnlCount > 0)) {
-                channelMask = mChannelMasks[i];
-                channelCount = cnlCount;
-            }
-        }
-        return channelMask;
-    }
-
-    uint32_t channelCount = 0;
-    uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
-
-    // For mixed output and inputs, use max mixer channel count. Do not
-    // limit channel count otherwise
-    if (mType != AUDIO_PORT_TYPE_MIX) {
-        maxCount = UINT_MAX;
-    }
-    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
-        uint32_t cnlCount;
-        if (mUseInChannelMask) {
-            cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
-        } else {
-            cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
-        }
-        if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
-            channelMask = mChannelMasks[i];
-            channelCount = cnlCount;
-        }
-    }
-    return channelMask;
-}
-
-/* format in order of increasing preference */
-const audio_format_t AudioPolicyManager::AudioPort::sPcmFormatCompareTable[] = {
-        AUDIO_FORMAT_DEFAULT,
-        AUDIO_FORMAT_PCM_16_BIT,
-        AUDIO_FORMAT_PCM_8_24_BIT,
-        AUDIO_FORMAT_PCM_24_BIT_PACKED,
-        AUDIO_FORMAT_PCM_32_BIT,
-        AUDIO_FORMAT_PCM_FLOAT,
-};
-
-int AudioPolicyManager::AudioPort::compareFormats(audio_format_t format1,
-                                                  audio_format_t format2)
-{
-    // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
-    // compressed format and better than any PCM format. This is by design of pickFormat()
-    if (!audio_is_linear_pcm(format1)) {
-        if (!audio_is_linear_pcm(format2)) {
-            return 0;
-        }
-        return 1;
-    }
-    if (!audio_is_linear_pcm(format2)) {
-        return -1;
-    }
-
-    int index1 = -1, index2 = -1;
-    for (size_t i = 0;
-            (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
-            i ++) {
-        if (sPcmFormatCompareTable[i] == format1) {
-            index1 = i;
-        }
-        if (sPcmFormatCompareTable[i] == format2) {
-            index2 = i;
-        }
-    }
-    // format1 not found => index1 < 0 => format2 > format1
-    // format2 not found => index2 < 0 => format2 < format1
-    return index1 - index2;
-}
-
-audio_format_t AudioPolicyManager::AudioPort::pickFormat() const
-{
-    // special case for uninitialized dynamic profile
-    if (mFormats.size() == 1 && mFormats[0] == 0) {
-        return AUDIO_FORMAT_DEFAULT;
-    }
-
-    audio_format_t format = AUDIO_FORMAT_DEFAULT;
-    audio_format_t bestFormat =
-            AudioPolicyManager::AudioPort::sPcmFormatCompareTable[
-                ARRAY_SIZE(AudioPolicyManager::AudioPort::sPcmFormatCompareTable) - 1];
-    // For mixed output and inputs, use best mixer output format. Do not
-    // limit format otherwise
-    if ((mType != AUDIO_PORT_TYPE_MIX) ||
-            ((mRole == AUDIO_PORT_ROLE_SOURCE) &&
-             (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) != 0)))) {
-        bestFormat = AUDIO_FORMAT_INVALID;
-    }
-
-    for (size_t i = 0; i < mFormats.size(); i ++) {
-        if ((compareFormats(mFormats[i], format) > 0) &&
-                (compareFormats(mFormats[i], bestFormat) <= 0)) {
-            format = mFormats[i];
-        }
-    }
-    return format;
-}
-
-status_t AudioPolicyManager::AudioPort::checkGain(const struct audio_gain_config *gainConfig,
-                                                  int index) const
-{
-    if (index < 0 || (size_t)index >= mGains.size()) {
-        return BAD_VALUE;
-    }
-    return mGains[index]->checkConfig(gainConfig);
-}
-
-void AudioPolicyManager::AudioPort::dump(int fd, int spaces) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    if (mName.size() != 0) {
-        snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
-        result.append(buffer);
-    }
-
-    if (mSamplingRates.size() != 0) {
-        snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, "");
-        result.append(buffer);
-        for (size_t i = 0; i < mSamplingRates.size(); i++) {
-            if (i == 0 && mSamplingRates[i] == 0) {
-                snprintf(buffer, SIZE, "Dynamic");
-            } else {
-                snprintf(buffer, SIZE, "%d", mSamplingRates[i]);
-            }
-            result.append(buffer);
-            result.append(i == (mSamplingRates.size() - 1) ? "" : ", ");
-        }
-        result.append("\n");
-    }
-
-    if (mChannelMasks.size() != 0) {
-        snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, "");
-        result.append(buffer);
-        for (size_t i = 0; i < mChannelMasks.size(); i++) {
-            ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]);
-
-            if (i == 0 && mChannelMasks[i] == 0) {
-                snprintf(buffer, SIZE, "Dynamic");
-            } else {
-                snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]);
-            }
-            result.append(buffer);
-            result.append(i == (mChannelMasks.size() - 1) ? "" : ", ");
-        }
-        result.append("\n");
-    }
-
-    if (mFormats.size() != 0) {
-        snprintf(buffer, SIZE, "%*s- formats: ", spaces, "");
-        result.append(buffer);
-        for (size_t i = 0; i < mFormats.size(); i++) {
-            const char *formatStr = enumToString(sFormatNameToEnumTable,
-                                                 ARRAY_SIZE(sFormatNameToEnumTable),
-                                                 mFormats[i]);
-            if (i == 0 && strcmp(formatStr, "") == 0) {
-                snprintf(buffer, SIZE, "Dynamic");
-            } else {
-                snprintf(buffer, SIZE, "%s", formatStr);
-            }
-            result.append(buffer);
-            result.append(i == (mFormats.size() - 1) ? "" : ", ");
-        }
-        result.append("\n");
-    }
-    write(fd, result.string(), result.size());
-    if (mGains.size() != 0) {
-        snprintf(buffer, SIZE, "%*s- gains:\n", spaces, "");
-        write(fd, buffer, strlen(buffer) + 1);
-        result.append(buffer);
-        for (size_t i = 0; i < mGains.size(); i++) {
-            mGains[i]->dump(fd, spaces + 2, i);
-        }
-    }
-}
-
-// --- AudioGain class implementation
-
-AudioPolicyManager::AudioGain::AudioGain(int index, bool useInChannelMask)
-{
-    mIndex = index;
-    mUseInChannelMask = useInChannelMask;
-    memset(&mGain, 0, sizeof(struct audio_gain));
-}
-
-void AudioPolicyManager::AudioGain::getDefaultConfig(struct audio_gain_config *config)
-{
-    config->index = mIndex;
-    config->mode = mGain.mode;
-    config->channel_mask = mGain.channel_mask;
-    if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
-        config->values[0] = mGain.default_value;
-    } else {
-        uint32_t numValues;
-        if (mUseInChannelMask) {
-            numValues = audio_channel_count_from_in_mask(mGain.channel_mask);
-        } else {
-            numValues = audio_channel_count_from_out_mask(mGain.channel_mask);
-        }
-        for (size_t i = 0; i < numValues; i++) {
-            config->values[i] = mGain.default_value;
-        }
-    }
-    if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
-        config->ramp_duration_ms = mGain.min_ramp_ms;
-    }
-}
-
-status_t AudioPolicyManager::AudioGain::checkConfig(const struct audio_gain_config *config)
-{
-    if ((config->mode & ~mGain.mode) != 0) {
-        return BAD_VALUE;
-    }
-    if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
-        if ((config->values[0] < mGain.min_value) ||
-                    (config->values[0] > mGain.max_value)) {
-            return BAD_VALUE;
-        }
-    } else {
-        if ((config->channel_mask & ~mGain.channel_mask) != 0) {
-            return BAD_VALUE;
-        }
-        uint32_t numValues;
-        if (mUseInChannelMask) {
-            numValues = audio_channel_count_from_in_mask(config->channel_mask);
-        } else {
-            numValues = audio_channel_count_from_out_mask(config->channel_mask);
-        }
-        for (size_t i = 0; i < numValues; i++) {
-            if ((config->values[i] < mGain.min_value) ||
-                    (config->values[i] > mGain.max_value)) {
-                return BAD_VALUE;
-            }
-        }
-    }
-    if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
-        if ((config->ramp_duration_ms < mGain.min_ramp_ms) ||
-                    (config->ramp_duration_ms > mGain.max_ramp_ms)) {
-            return BAD_VALUE;
-        }
-    }
-    return NO_ERROR;
-}
-
-void AudioPolicyManager::AudioGain::dump(int fd, int spaces, int index) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms);
-    result.append(buffer);
-
-    write(fd, result.string(), result.size());
-}
-
-// --- AudioPortConfig class implementation
-
-AudioPolicyManager::AudioPortConfig::AudioPortConfig()
-{
-    mSamplingRate = 0;
-    mChannelMask = AUDIO_CHANNEL_NONE;
-    mFormat = AUDIO_FORMAT_INVALID;
-    mGain.index = -1;
-}
-
-status_t AudioPolicyManager::AudioPortConfig::applyAudioPortConfig(
-                                                        const struct audio_port_config *config,
-                                                        struct audio_port_config *backupConfig)
-{
-    struct audio_port_config localBackupConfig;
-    status_t status = NO_ERROR;
-
-    localBackupConfig.config_mask = config->config_mask;
-    toAudioPortConfig(&localBackupConfig);
-
-    sp<AudioPort> audioport = getAudioPort();
-    if (audioport == 0) {
-        status = NO_INIT;
-        goto exit;
-    }
-    if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
-        status = audioport->checkExactSamplingRate(config->sample_rate);
-        if (status != NO_ERROR) {
-            goto exit;
-        }
-        mSamplingRate = config->sample_rate;
-    }
-    if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
-        status = audioport->checkExactChannelMask(config->channel_mask);
-        if (status != NO_ERROR) {
-            goto exit;
-        }
-        mChannelMask = config->channel_mask;
-    }
-    if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
-        status = audioport->checkFormat(config->format);
-        if (status != NO_ERROR) {
-            goto exit;
-        }
-        mFormat = config->format;
-    }
-    if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
-        status = audioport->checkGain(&config->gain, config->gain.index);
-        if (status != NO_ERROR) {
-            goto exit;
-        }
-        mGain = config->gain;
-    }
-
-exit:
-    if (status != NO_ERROR) {
-        applyAudioPortConfig(&localBackupConfig);
-    }
-    if (backupConfig != NULL) {
-        *backupConfig = localBackupConfig;
-    }
-    return status;
-}
-
-void AudioPolicyManager::AudioPortConfig::toAudioPortConfig(
-                                                    struct audio_port_config *dstConfig,
-                                                    const struct audio_port_config *srcConfig) const
-{
-    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
-        dstConfig->sample_rate = mSamplingRate;
-        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) {
-            dstConfig->sample_rate = srcConfig->sample_rate;
-        }
-    } else {
-        dstConfig->sample_rate = 0;
-    }
-    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
-        dstConfig->channel_mask = mChannelMask;
-        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) {
-            dstConfig->channel_mask = srcConfig->channel_mask;
-        }
-    } else {
-        dstConfig->channel_mask = AUDIO_CHANNEL_NONE;
-    }
-    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
-        dstConfig->format = mFormat;
-        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) {
-            dstConfig->format = srcConfig->format;
-        }
-    } else {
-        dstConfig->format = AUDIO_FORMAT_INVALID;
-    }
-    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) {
-        dstConfig->gain = mGain;
-        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)) {
-            dstConfig->gain = srcConfig->gain;
-        }
-    } else {
-        dstConfig->gain.index = -1;
-    }
-    if (dstConfig->gain.index != -1) {
-        dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
-    } else {
-        dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
-    }
-}
-
-// --- IOProfile class implementation
-
-AudioPolicyManager::IOProfile::IOProfile(const String8& name, audio_port_role_t role,
-                                         const sp<HwModule>& module)
-    : AudioPort(name, AUDIO_PORT_TYPE_MIX, role, module)
-{
-}
-
-AudioPolicyManager::IOProfile::~IOProfile()
-{
-}
-
-// checks if the IO profile is compatible with specified parameters.
-// Sampling rate, format and channel mask must be specified in order to
-// get a valid a match
-bool AudioPolicyManager::IOProfile::isCompatibleProfile(audio_devices_t device,
-                                                            uint32_t samplingRate,
-                                                            uint32_t *updatedSamplingRate,
-                                                            audio_format_t format,
-                                                            audio_channel_mask_t channelMask,
-                                                            uint32_t flags) const
-{
-    const bool isPlaybackThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SOURCE;
-    const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
-    ALOG_ASSERT(isPlaybackThread != isRecordThread);
-
-    if ((mSupportedDevices.types() & device) != device) {
-        return false;
-    }
-
-    if (samplingRate == 0) {
-         return false;
-    }
-    uint32_t myUpdatedSamplingRate = samplingRate;
-    if (isPlaybackThread && checkExactSamplingRate(samplingRate) != NO_ERROR) {
-         return false;
-    }
-    if (isRecordThread && checkCompatibleSamplingRate(samplingRate, &myUpdatedSamplingRate) !=
-            NO_ERROR) {
-         return false;
-    }
-
-    if (!audio_is_valid_format(format) || checkFormat(format) != NO_ERROR) {
-        return false;
-    }
-
-    if (isPlaybackThread && (!audio_is_output_channel(channelMask) ||
-            checkExactChannelMask(channelMask) != NO_ERROR)) {
-        return false;
-    }
-    if (isRecordThread && (!audio_is_input_channel(channelMask) ||
-            checkCompatibleChannelMask(channelMask) != NO_ERROR)) {
-        return false;
-    }
-
-    if (isPlaybackThread && (mFlags & flags) != flags) {
-        return false;
-    }
-    // The only input flag that is allowed to be different is the fast flag.
-    // An existing fast stream is compatible with a normal track request.
-    // An existing normal stream is compatible with a fast track request,
-    // but the fast request will be denied by AudioFlinger and converted to normal track.
-    if (isRecordThread && ((mFlags ^ flags) &
-            ~AUDIO_INPUT_FLAG_FAST)) {
-        return false;
-    }
-
-    if (updatedSamplingRate != NULL) {
-        *updatedSamplingRate = myUpdatedSamplingRate;
-    }
-    return true;
-}
-
-void AudioPolicyManager::IOProfile::dump(int fd)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    AudioPort::dump(fd, 4);
-
-    snprintf(buffer, SIZE, "    - flags: 0x%04x\n", mFlags);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "    - devices:\n");
-    result.append(buffer);
-    write(fd, result.string(), result.size());
-    for (size_t i = 0; i < mSupportedDevices.size(); i++) {
-        mSupportedDevices[i]->dump(fd, 6, i);
-    }
-}
-
-void AudioPolicyManager::IOProfile::log()
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    ALOGV("    - sampling rates: ");
-    for (size_t i = 0; i < mSamplingRates.size(); i++) {
-        ALOGV("  %d", mSamplingRates[i]);
-    }
-
-    ALOGV("    - channel masks: ");
-    for (size_t i = 0; i < mChannelMasks.size(); i++) {
-        ALOGV("  0x%04x", mChannelMasks[i]);
-    }
-
-    ALOGV("    - formats: ");
-    for (size_t i = 0; i < mFormats.size(); i++) {
-        ALOGV("  0x%08x", mFormats[i]);
-    }
-
-    ALOGV("    - devices: 0x%04x\n", mSupportedDevices.types());
-    ALOGV("    - flags: 0x%04x\n", mFlags);
-}
-
-
-// --- DeviceDescriptor implementation
-
-
-AudioPolicyManager::DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) :
-                     AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
-                               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
-                                                              AUDIO_PORT_ROLE_SOURCE,
-                             NULL),
-                     mDeviceType(type), mAddress(""), mId(0)
-{
-    if (mGains.size() > 0) {
-        mGains[0]->getDefaultConfig(&mGain);
-    }
-}
-
-bool AudioPolicyManager::DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
-{
-    // Devices are considered equal if they:
-    // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE)
-    // - have the same address or one device does not specify the address
-    // - have the same channel mask or one device does not specify the channel mask
-    return (mDeviceType == other->mDeviceType) &&
-           (mAddress == "" || other->mAddress == "" || mAddress == other->mAddress) &&
-           (mChannelMask == 0 || other->mChannelMask == 0 ||
-                mChannelMask == other->mChannelMask);
-}
-
-void AudioPolicyManager::DeviceVector::refreshTypes()
-{
-    mDeviceTypes = AUDIO_DEVICE_NONE;
-    for(size_t i = 0; i < size(); i++) {
-        mDeviceTypes |= itemAt(i)->mDeviceType;
-    }
-    ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
-}
-
-ssize_t AudioPolicyManager::DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
-{
-    for(size_t i = 0; i < size(); i++) {
-        if (item->equals(itemAt(i))) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-ssize_t AudioPolicyManager::DeviceVector::add(const sp<DeviceDescriptor>& item)
-{
-    ssize_t ret = indexOf(item);
-
-    if (ret < 0) {
-        ret = SortedVector::add(item);
-        if (ret >= 0) {
-            refreshTypes();
-        }
-    } else {
-        ALOGW("DeviceVector::add device %08x already in", item->mDeviceType);
-        ret = -1;
-    }
-    return ret;
-}
-
-ssize_t AudioPolicyManager::DeviceVector::remove(const sp<DeviceDescriptor>& item)
-{
-    size_t i;
-    ssize_t ret = indexOf(item);
-
-    if (ret < 0) {
-        ALOGW("DeviceVector::remove device %08x not in", item->mDeviceType);
-    } else {
-        ret = SortedVector::removeAt(ret);
-        if (ret >= 0) {
-            refreshTypes();
-        }
-    }
-    return ret;
-}
-
-void AudioPolicyManager::DeviceVector::loadDevicesFromType(audio_devices_t types)
-{
-    DeviceVector deviceList;
-
-    uint32_t role_bit = AUDIO_DEVICE_BIT_IN & types;
-    types &= ~role_bit;
-
-    while (types) {
-        uint32_t i = 31 - __builtin_clz(types);
-        uint32_t type = 1 << i;
-        types &= ~type;
-        add(new DeviceDescriptor(String8(""), type | role_bit));
-    }
-}
-
-void AudioPolicyManager::DeviceVector::loadDevicesFromName(char *name,
-                                                           const DeviceVector& declaredDevices)
-{
-    char *devName = strtok(name, "|");
-    while (devName != NULL) {
-        if (strlen(devName) != 0) {
-            audio_devices_t type = stringToEnum(sDeviceNameToEnumTable,
-                                 ARRAY_SIZE(sDeviceNameToEnumTable),
-                                 devName);
-            if (type != AUDIO_DEVICE_NONE) {
-                sp<DeviceDescriptor> dev = new DeviceDescriptor(String8(""), type);
-                if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
-                    dev->mAddress = String8("0");
-                }
-                add(dev);
-            } else {
-                sp<DeviceDescriptor> deviceDesc =
-                        declaredDevices.getDeviceFromName(String8(devName));
-                if (deviceDesc != 0) {
-                    add(deviceDesc);
-                }
-            }
-         }
-        devName = strtok(NULL, "|");
-     }
-}
-
-sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDevice(
-                                                        audio_devices_t type, String8 address) const
-{
-    sp<DeviceDescriptor> device;
-    for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->mDeviceType == type) {
-            device = itemAt(i);
-            if (itemAt(i)->mAddress = address) {
-                break;
-            }
-        }
-    }
-    ALOGV("DeviceVector::getDevice() for type %d address %s found %p",
-          type, address.string(), device.get());
-    return device;
-}
-
-sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDeviceFromId(
-                                                                    audio_port_handle_t id) const
-{
-    sp<DeviceDescriptor> device;
-    for (size_t i = 0; i < size(); i++) {
-        ALOGV("DeviceVector::getDeviceFromId(%d) itemAt(%zu)->mId %d", id, i, itemAt(i)->mId);
-        if (itemAt(i)->mId == id) {
-            device = itemAt(i);
-            break;
-        }
-    }
-    return device;
-}
-
-AudioPolicyManager::DeviceVector AudioPolicyManager::DeviceVector::getDevicesFromType(
-                                                                        audio_devices_t type) const
-{
-    DeviceVector devices;
-    for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
-        if (itemAt(i)->mDeviceType & type & ~AUDIO_DEVICE_BIT_IN) {
-            devices.add(itemAt(i));
-            type &= ~itemAt(i)->mDeviceType;
-            ALOGV("DeviceVector::getDevicesFromType() for type %x found %p",
-                  itemAt(i)->mDeviceType, itemAt(i).get());
-        }
-    }
-    return devices;
-}
-
-AudioPolicyManager::DeviceVector AudioPolicyManager::DeviceVector::getDevicesFromTypeAddr(
-        audio_devices_t type, String8 address) const
-{
-    DeviceVector devices;
-    //ALOGV("   looking for device=%x, addr=%s", type, address.string());
-    for (size_t i = 0; i < size(); i++) {
-        //ALOGV("     at i=%d: device=%x, addr=%s",
-        //        i, itemAt(i)->mDeviceType, itemAt(i)->mAddress.string());
-        if (itemAt(i)->mDeviceType == type) {
-            if (itemAt(i)->mAddress == address) {
-                //ALOGV("      found matching address %s", address.string());
-                devices.add(itemAt(i));
-            }
-        }
-    }
-    return devices;
-}
-
-sp<AudioPolicyManager::DeviceDescriptor> AudioPolicyManager::DeviceVector::getDeviceFromName(
-        const String8& name) const
-{
-    sp<DeviceDescriptor> device;
-    for (size_t i = 0; i < size(); i++) {
-        if (itemAt(i)->mName == name) {
-            device = itemAt(i);
-            break;
-        }
-    }
-    return device;
-}
-
-void AudioPolicyManager::DeviceDescriptor::toAudioPortConfig(
-                                                    struct audio_port_config *dstConfig,
-                                                    const struct audio_port_config *srcConfig) const
-{
-    dstConfig->config_mask = AUDIO_PORT_CONFIG_CHANNEL_MASK|AUDIO_PORT_CONFIG_GAIN;
-    if (srcConfig != NULL) {
-        dstConfig->config_mask |= srcConfig->config_mask;
-    }
-
-    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
-
-    dstConfig->id = mId;
-    dstConfig->role = audio_is_output_device(mDeviceType) ?
-                        AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
-    dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
-    dstConfig->ext.device.type = mDeviceType;
-    dstConfig->ext.device.hw_module = mModule->mHandle;
-    strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
-}
-
-void AudioPolicyManager::DeviceDescriptor::toAudioPort(struct audio_port *port) const
-{
-    ALOGV("DeviceDescriptor::toAudioPort() handle %d type %x", mId, mDeviceType);
-    AudioPort::toAudioPort(port);
-    port->id = mId;
-    toAudioPortConfig(&port->active_config);
-    port->ext.device.type = mDeviceType;
-    port->ext.device.hw_module = mModule->mHandle;
-    strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
-}
-
-status_t AudioPolicyManager::DeviceDescriptor::dump(int fd, int spaces, int index) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    snprintf(buffer, SIZE, "%*sDevice %d:\n", spaces, "", index+1);
-    result.append(buffer);
-    if (mId != 0) {
-        snprintf(buffer, SIZE, "%*s- id: %2d\n", spaces, "", mId);
-        result.append(buffer);
-    }
-    snprintf(buffer, SIZE, "%*s- type: %-48s\n", spaces, "",
-                                              enumToString(sDeviceNameToEnumTable,
-                                                           ARRAY_SIZE(sDeviceNameToEnumTable),
-                                                           mDeviceType));
-    result.append(buffer);
-    if (mAddress.size() != 0) {
-        snprintf(buffer, SIZE, "%*s- address: %-32s\n", spaces, "", mAddress.string());
-        result.append(buffer);
-    }
-    write(fd, result.string(), result.size());
-    AudioPort::dump(fd, spaces);
-
-    return NO_ERROR;
-}
-
-status_t AudioPolicyManager::AudioPatch::dump(int fd, int spaces, int index) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-
-    snprintf(buffer, SIZE, "%*sAudio patch %d:\n", spaces, "", index+1);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- handle: %2d\n", spaces, "", mHandle);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- audio flinger handle: %2d\n", spaces, "", mAfPatchHandle);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "%*s- %d sources:\n", spaces, "", mPatch.num_sources);
-    result.append(buffer);
-    for (size_t i = 0; i < mPatch.num_sources; i++) {
-        if (mPatch.sources[i].type == AUDIO_PORT_TYPE_DEVICE) {
-            snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
-                     mPatch.sources[i].id, enumToString(sDeviceNameToEnumTable,
-                                                        ARRAY_SIZE(sDeviceNameToEnumTable),
-                                                        mPatch.sources[i].ext.device.type));
-        } else {
-            snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "",
-                     mPatch.sources[i].id, mPatch.sources[i].ext.mix.handle);
-        }
-        result.append(buffer);
-    }
-    snprintf(buffer, SIZE, "%*s- %d sinks:\n", spaces, "", mPatch.num_sinks);
-    result.append(buffer);
-    for (size_t i = 0; i < mPatch.num_sinks; i++) {
-        if (mPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE) {
-            snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
-                     mPatch.sinks[i].id, enumToString(sDeviceNameToEnumTable,
-                                                        ARRAY_SIZE(sDeviceNameToEnumTable),
-                                                        mPatch.sinks[i].ext.device.type));
-        } else {
-            snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "",
-                     mPatch.sinks[i].id, mPatch.sinks[i].ext.mix.handle);
-        }
-        result.append(buffer);
-    }
-
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
 
 // --- audio_policy.conf file parsing
-
-uint32_t AudioPolicyManager::parseOutputFlagNames(char *name)
-{
-    uint32_t flag = 0;
-
-    // it is OK to cast name to non const here as we are not going to use it after
-    // strtok() modifies it
-    char *flagName = strtok(name, "|");
-    while (flagName != NULL) {
-        if (strlen(flagName) != 0) {
-            flag |= stringToEnum(sOutputFlagNameToEnumTable,
-                               ARRAY_SIZE(sOutputFlagNameToEnumTable),
-                               flagName);
-        }
-        flagName = strtok(NULL, "|");
-    }
-    //force direct flag if offload flag is set: offloading implies a direct output stream
-    // and all common behaviors are driven by checking only the direct flag
-    // this should normally be set appropriately in the policy configuration file
-    if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
-        flag |= AUDIO_OUTPUT_FLAG_DIRECT;
-    }
-
-    return flag;
-}
-
-uint32_t AudioPolicyManager::parseInputFlagNames(char *name)
-{
-    uint32_t flag = 0;
-
-    // it is OK to cast name to non const here as we are not going to use it after
-    // strtok() modifies it
-    char *flagName = strtok(name, "|");
-    while (flagName != NULL) {
-        if (strlen(flagName) != 0) {
-            flag |= stringToEnum(sInputFlagNameToEnumTable,
-                               ARRAY_SIZE(sInputFlagNameToEnumTable),
-                               flagName);
-        }
-        flagName = strtok(NULL, "|");
-    }
-    return flag;
-}
-
-audio_devices_t AudioPolicyManager::parseDeviceNames(char *name)
-{
-    uint32_t device = 0;
-
-    char *devName = strtok(name, "|");
-    while (devName != NULL) {
-        if (strlen(devName) != 0) {
-            device |= stringToEnum(sDeviceNameToEnumTable,
-                                 ARRAY_SIZE(sDeviceNameToEnumTable),
-                                 devName);
-         }
-        devName = strtok(NULL, "|");
-     }
-    return device;
-}
-
+// TODO candidate to be moved to ConfigParsingUtils
 void AudioPolicyManager::loadHwModule(cnode *root)
 {
     status_t status = NAME_NOT_FOUND;
@@ -7272,6 +5557,7 @@
     }
 }
 
+// TODO candidate to be moved to ConfigParsingUtils
 void AudioPolicyManager::loadHwModules(cnode *root)
 {
     cnode *node = config_find(root, AUDIO_HW_MODULE_TAG);
@@ -7287,6 +5573,7 @@
     }
 }
 
+// TODO candidate to be moved to ConfigParsingUtils
 void AudioPolicyManager::loadGlobalConfig(cnode *root, const sp<HwModule>& module)
 {
     cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
@@ -7307,11 +5594,12 @@
             ALOGV("loadGlobalConfig() Attached Output Devices %08x",
                   mAvailableOutputDevices.types());
         } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
-            audio_devices_t device = (audio_devices_t)stringToEnum(sDeviceNameToEnumTable,
-                                              ARRAY_SIZE(sDeviceNameToEnumTable),
-                                              (char *)node->value);
+            audio_devices_t device = (audio_devices_t)ConfigParsingUtils::stringToEnum(
+                    sDeviceNameToEnumTable,
+                    ARRAY_SIZE(sDeviceNameToEnumTable),
+                    (char *)node->value);
             if (device != AUDIO_DEVICE_NONE) {
-                mDefaultOutputDevice = new DeviceDescriptor(String8(""), device);
+                mDefaultOutputDevice = new DeviceDescriptor(String8("default-output"), device);
             } else {
                 ALOGW("loadGlobalConfig() default device not specified");
             }
@@ -7321,7 +5609,7 @@
                                                        declaredDevices);
             ALOGV("loadGlobalConfig() Available InputDevices %08x", mAvailableInputDevices.types());
         } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
-            mSpeakerDrcEnabled = stringToBool((char *)node->value);
+            mSpeakerDrcEnabled = ConfigParsingUtils::stringToBool((char *)node->value);
             ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", mSpeakerDrcEnabled);
         } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) {
             uint32_t major, minor;
@@ -7334,6 +5622,7 @@
     }
 }
 
+// TODO candidate to be moved to ConfigParsingUtils
 status_t AudioPolicyManager::loadAudioPolicyConfig(const char *path)
 {
     cnode *root;
@@ -7362,8 +5651,8 @@
 {
     sp<HwModule> module;
     sp<IOProfile> profile;
-    sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(String8(""),
-                                                                   AUDIO_DEVICE_IN_BUILTIN_MIC);
+    sp<DeviceDescriptor> defaultInputDevice =
+                    new DeviceDescriptor(String8("builtin-mic"), AUDIO_DEVICE_IN_BUILTIN_MIC);
     mAvailableOutputDevices.add(mDefaultOutputDevice);
     mAvailableInputDevices.add(defaultInputDevice);
 
@@ -7396,14 +5685,27 @@
     if ((attr->flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) {
         return AUDIO_STREAM_BLUETOOTH_SCO;
     }
+    if ((attr->flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) {
+        return AUDIO_STREAM_TTS;
+    }
 
     // usage to stream type mapping
     switch (attr->usage) {
     case AUDIO_USAGE_MEDIA:
     case AUDIO_USAGE_GAME:
-    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
     case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
         return AUDIO_STREAM_MUSIC;
+    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+        if (isStreamActive(AUDIO_STREAM_ALARM)) {
+            return AUDIO_STREAM_ALARM;
+        }
+        if (isStreamActive(AUDIO_STREAM_RING)) {
+            return AUDIO_STREAM_RING;
+        }
+        if (isInCall()) {
+            return AUDIO_STREAM_VOICE_CALL;
+        }
+        return AUDIO_STREAM_ACCESSIBILITY;
     case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
         return AUDIO_STREAM_SYSTEM;
     case AUDIO_USAGE_VOICE_COMMUNICATION:
@@ -7429,4 +5731,36 @@
         return AUDIO_STREAM_MUSIC;
     }
 }
+
+bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa) {
+    // has flags that map to a strategy?
+    if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) {
+        return true;
+    }
+
+    // has known usage?
+    switch (paa->usage) {
+    case AUDIO_USAGE_UNKNOWN:
+    case AUDIO_USAGE_MEDIA:
+    case AUDIO_USAGE_VOICE_COMMUNICATION:
+    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+    case AUDIO_USAGE_ALARM:
+    case AUDIO_USAGE_NOTIFICATION:
+    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+    case AUDIO_USAGE_NOTIFICATION_EVENT:
+    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+    case AUDIO_USAGE_GAME:
+    case AUDIO_USAGE_VIRTUAL_SOURCE:
+        break;
+    default:
+        return false;
+    }
+    return true;
+}
+
 }; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
new file mode 100644
index 0000000..61ea6f2
--- /dev/null
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -0,0 +1,560 @@
+/*
+ * 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.
+ */
+
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <cutils/config_utils.h>
+#include <cutils/misc.h>
+#include <utils/Timers.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/SortedVector.h>
+#include <media/AudioPolicy.h>
+#include "AudioPolicyInterface.h"
+
+#include "Gains.h"
+#include "Ports.h"
+#include "ConfigParsingUtils.h"
+#include "Devices.h"
+#include "IOProfile.h"
+#include "HwModule.h"
+#include "AudioInputDescriptor.h"
+#include "AudioOutputDescriptor.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// Attenuation applied to STRATEGY_SONIFICATION streams when a headset is connected: 6dB
+#define SONIFICATION_HEADSET_VOLUME_FACTOR 0.5
+// Min volume for STRATEGY_SONIFICATION streams when limited by music volume: -36dB
+#define SONIFICATION_HEADSET_VOLUME_MIN  0.016
+// Time in milliseconds during which we consider that music is still active after a music
+// track was stopped - see computeVolume()
+#define SONIFICATION_HEADSET_MUSIC_DELAY  5000
+// Time in milliseconds after media stopped playing during which we consider that the
+// sonification should be as unobtrusive as during the time media was playing.
+#define SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY 5000
+// Time in milliseconds during witch some streams are muted while the audio path
+// is switched
+#define MUTE_TIME_MS 2000
+
+#define NUM_TEST_OUTPUTS 5
+
+#define NUM_VOL_CURVE_KNEES 2
+
+// Default minimum length allowed for offloading a compressed track
+// Can be overridden by the audio.offload.min.duration.secs property
+#define OFFLOAD_DEFAULT_MIN_DURATION_SECS 60
+
+#define MAX_MIXER_SAMPLING_RATE 48000
+#define MAX_MIXER_CHANNEL_COUNT 8
+
+// ----------------------------------------------------------------------------
+// AudioPolicyManager implements audio policy manager behavior common to all platforms.
+// ----------------------------------------------------------------------------
+
+class AudioPolicyManager: public AudioPolicyInterface
+#ifdef AUDIO_POLICY_TEST
+    , public Thread
+#endif //AUDIO_POLICY_TEST
+{
+
+public:
+                AudioPolicyManager(AudioPolicyClientInterface *clientInterface);
+        virtual ~AudioPolicyManager();
+
+        // AudioPolicyInterface
+        virtual status_t setDeviceConnectionState(audio_devices_t device,
+                                                          audio_policy_dev_state_t state,
+                                                          const char *device_address,
+                                                          const char *device_name);
+        virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
+                                                                              const char *device_address);
+        virtual void setPhoneState(audio_mode_t state);
+        virtual void setForceUse(audio_policy_force_use_t usage,
+                                 audio_policy_forced_cfg_t config);
+        virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
+        virtual void setSystemProperty(const char* property, const char* value);
+        virtual status_t initCheck();
+        virtual audio_io_handle_t getOutput(audio_stream_type_t stream,
+                                            uint32_t samplingRate,
+                                            audio_format_t format,
+                                            audio_channel_mask_t channelMask,
+                                            audio_output_flags_t flags,
+                                            const audio_offload_info_t *offloadInfo);
+        virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+                                          audio_io_handle_t *output,
+                                          audio_session_t session,
+                                          audio_stream_type_t *stream,
+                                          uint32_t samplingRate,
+                                          audio_format_t format,
+                                          audio_channel_mask_t channelMask,
+                                          audio_output_flags_t flags,
+                                          const audio_offload_info_t *offloadInfo);
+        virtual status_t startOutput(audio_io_handle_t output,
+                                     audio_stream_type_t stream,
+                                     audio_session_t session);
+        virtual status_t stopOutput(audio_io_handle_t output,
+                                    audio_stream_type_t stream,
+                                    audio_session_t session);
+        virtual void releaseOutput(audio_io_handle_t output,
+                                   audio_stream_type_t stream,
+                                   audio_session_t session);
+        virtual status_t getInputForAttr(const audio_attributes_t *attr,
+                                         audio_io_handle_t *input,
+                                         audio_session_t session,
+                                         uint32_t samplingRate,
+                                         audio_format_t format,
+                                         audio_channel_mask_t channelMask,
+                                         audio_input_flags_t flags,
+                                         input_type_t *inputType);
+
+        // indicates to the audio policy manager that the input starts being used.
+        virtual status_t startInput(audio_io_handle_t input,
+                                    audio_session_t session);
+
+        // indicates to the audio policy manager that the input stops being used.
+        virtual status_t stopInput(audio_io_handle_t input,
+                                   audio_session_t session);
+        virtual void releaseInput(audio_io_handle_t input,
+                                  audio_session_t session);
+        virtual void closeAllInputs();
+        virtual void initStreamVolume(audio_stream_type_t stream,
+                                                    int indexMin,
+                                                    int indexMax);
+        virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
+                                              int index,
+                                              audio_devices_t device);
+        virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
+                                              int *index,
+                                              audio_devices_t device);
+
+        // return the strategy corresponding to a given stream type
+        virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
+        // return the strategy corresponding to the given audio attributes
+        virtual uint32_t getStrategyForAttr(const audio_attributes_t *attr);
+
+        // return the enabled output devices for the given stream type
+        virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
+
+        virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc = NULL);
+        virtual status_t registerEffect(const effect_descriptor_t *desc,
+                                        audio_io_handle_t io,
+                                        uint32_t strategy,
+                                        int session,
+                                        int id);
+        virtual status_t unregisterEffect(int id);
+        virtual status_t setEffectEnabled(int id, bool enabled);
+
+        virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+        // return whether a stream is playing remotely, override to change the definition of
+        //   local/remote playback, used for instance by notification manager to not make
+        //   media players lose audio focus when not playing locally
+        //   For the base implementation, "remotely" means playing during screen mirroring which
+        //   uses an output for playback with a non-empty, non "0" address.
+        virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+        virtual bool isSourceActive(audio_source_t source) const;
+
+        virtual status_t dump(int fd);
+
+        virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);
+
+        virtual status_t listAudioPorts(audio_port_role_t role,
+                                        audio_port_type_t type,
+                                        unsigned int *num_ports,
+                                        struct audio_port *ports,
+                                        unsigned int *generation);
+        virtual status_t getAudioPort(struct audio_port *port);
+        virtual status_t createAudioPatch(const struct audio_patch *patch,
+                                           audio_patch_handle_t *handle,
+                                           uid_t uid);
+        virtual status_t releaseAudioPatch(audio_patch_handle_t handle,
+                                              uid_t uid);
+        virtual status_t listAudioPatches(unsigned int *num_patches,
+                                          struct audio_patch *patches,
+                                          unsigned int *generation);
+        virtual status_t setAudioPortConfig(const struct audio_port_config *config);
+        virtual void clearAudioPatches(uid_t uid);
+
+        virtual status_t acquireSoundTriggerSession(audio_session_t *session,
+                                               audio_io_handle_t *ioHandle,
+                                               audio_devices_t *device);
+
+        virtual status_t releaseSoundTriggerSession(audio_session_t session);
+
+        virtual status_t registerPolicyMixes(Vector<AudioMix> mixes);
+        virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes);
+
+        // Audio policy configuration file parsing (audio_policy.conf)
+        // TODO candidates to be moved to ConfigParsingUtils
+                void loadHwModule(cnode *root);
+                void loadHwModules(cnode *root);
+                void loadGlobalConfig(cnode *root, const sp<HwModule>& module);
+                status_t loadAudioPolicyConfig(const char *path);
+                void defaultAudioPolicyConfig(void);
+
+                // return the strategy corresponding to a given stream type
+                static routing_strategy getStrategy(audio_stream_type_t stream);
+
+                static uint32_t nextUniqueId();
+protected:
+
+        class EffectDescriptor : public RefBase
+        {
+        public:
+
+            status_t dump(int fd);
+
+            int mIo;                // io the effect is attached to
+            routing_strategy mStrategy; // routing strategy the effect is associated to
+            int mSession;               // audio session the effect is on
+            effect_descriptor_t mDesc;  // effect descriptor
+            bool mEnabled;              // enabled state: CPU load being used or not
+        };
+
+        void addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc);
+        void addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc);
+
+        // return appropriate device for streams handled by the specified strategy according to current
+        // phone state, connected devices...
+        // if fromCache is true, the device is returned from mDeviceForStrategy[],
+        // otherwise it is determine by current state
+        // (device connected,phone state, force use, a2dp output...)
+        // This allows to:
+        //  1 speed up process when the state is stable (when starting or stopping an output)
+        //  2 access to either current device selection (fromCache == true) or
+        // "future" device selection (fromCache == false) when called from a context
+        //  where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND
+        //  before updateDevicesAndOutputs() is called.
+        virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy,
+                                                     bool fromCache);
+
+        // change the route of the specified output. Returns the number of ms we have slept to
+        // allow new routing to take effect in certain cases.
+        virtual uint32_t setOutputDevice(audio_io_handle_t output,
+                             audio_devices_t device,
+                             bool force = false,
+                             int delayMs = 0,
+                             audio_patch_handle_t *patchHandle = NULL,
+                             const char* address = NULL);
+        status_t resetOutputDevice(audio_io_handle_t output,
+                                   int delayMs = 0,
+                                   audio_patch_handle_t *patchHandle = NULL);
+        status_t setInputDevice(audio_io_handle_t input,
+                                audio_devices_t device,
+                                bool force = false,
+                                audio_patch_handle_t *patchHandle = NULL);
+        status_t resetInputDevice(audio_io_handle_t input,
+                                  audio_patch_handle_t *patchHandle = NULL);
+
+        // select input device corresponding to requested audio source
+        virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource);
+
+        // return io handle of active input or 0 if no input is active
+        //    Only considers inputs from physical devices (e.g. main mic, headset mic) when
+        //    ignoreVirtualInputs is true.
+        audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
+
+        uint32_t activeInputsCount() const;
+
+        // initialize volume curves for each strategy and device category
+        void initializeVolumeCurves();
+
+        // compute the actual volume for a given stream according to the requested index and a particular
+        // device
+        virtual float computeVolume(audio_stream_type_t stream, int index,
+                                    audio_io_handle_t output, audio_devices_t device);
+
+        // check that volume change is permitted, compute and send new volume to audio hardware
+        virtual status_t checkAndSetVolume(audio_stream_type_t stream, int index,
+                                           audio_io_handle_t output,
+                                           audio_devices_t device,
+                                           int delayMs = 0, bool force = false);
+
+        // apply all stream volumes to the specified output and device
+        void applyStreamVolumes(audio_io_handle_t output, audio_devices_t device, int delayMs = 0, bool force = false);
+
+        // Mute or unmute all streams handled by the specified strategy on the specified output
+        void setStrategyMute(routing_strategy strategy,
+                             bool on,
+                             audio_io_handle_t output,
+                             int delayMs = 0,
+                             audio_devices_t device = (audio_devices_t)0);
+
+        // Mute or unmute the stream on the specified output
+        void setStreamMute(audio_stream_type_t stream,
+                           bool on,
+                           audio_io_handle_t output,
+                           int delayMs = 0,
+                           audio_devices_t device = (audio_devices_t)0);
+
+        // handle special cases for sonification strategy while in call: mute streams or replace by
+        // a special tone in the device used for communication
+        void handleIncallSonification(audio_stream_type_t stream, bool starting, bool stateChange);
+
+        // true if device is in a telephony or VoIP call
+        virtual bool isInCall();
+
+        // true if given state represents a device in a telephony or VoIP call
+        virtual bool isStateInCall(int state);
+
+        // when a device is connected, checks if an open output can be routed
+        // to this device. If none is open, tries to open one of the available outputs.
+        // Returns an output suitable to this device or 0.
+        // when a device is disconnected, checks if an output is not used any more and
+        // returns its handle if any.
+        // transfers the audio tracks and effects from one output thread to another accordingly.
+        status_t checkOutputsForDevice(const sp<DeviceDescriptor> devDesc,
+                                       audio_policy_dev_state_t state,
+                                       SortedVector<audio_io_handle_t>& outputs,
+                                       const String8 address);
+
+        status_t checkInputsForDevice(audio_devices_t device,
+                                      audio_policy_dev_state_t state,
+                                      SortedVector<audio_io_handle_t>& inputs,
+                                      const String8 address);
+
+        // close an output and its companion duplicating output.
+        void closeOutput(audio_io_handle_t output);
+
+        // close an input.
+        void closeInput(audio_io_handle_t input);
+
+        // checks and if necessary changes outputs used for all strategies.
+        // must be called every time a condition that affects the output choice for a given strategy
+        // changes: connected device, phone state, force use...
+        // Must be called before updateDevicesAndOutputs()
+        void checkOutputForStrategy(routing_strategy strategy);
+
+        // Same as checkOutputForStrategy() but for a all strategies in order of priority
+        void checkOutputForAllStrategies();
+
+        // manages A2DP output suspend/restore according to phone state and BT SCO usage
+        void checkA2dpSuspend();
+
+        // returns the A2DP output handle if it is open or 0 otherwise
+        audio_io_handle_t getA2dpOutput();
+
+        // selects the most appropriate device on output for current state
+        // must be called every time a condition that affects the device choice for a given output is
+        // changed: connected device, phone state, force use, output start, output stop..
+        // see getDeviceForStrategy() for the use of fromCache parameter
+        audio_devices_t getNewOutputDevice(audio_io_handle_t output, bool fromCache);
+
+        // updates cache of device used by all strategies (mDeviceForStrategy[])
+        // must be called every time a condition that affects the device choice for a given strategy is
+        // changed: connected device, phone state, force use...
+        // cached values are used by getDeviceForStrategy() if parameter fromCache is true.
+         // Must be called after checkOutputForAllStrategies()
+        void updateDevicesAndOutputs();
+
+        // selects the most appropriate device on input for current state
+        audio_devices_t getNewInputDevice(audio_io_handle_t input);
+
+        virtual uint32_t getMaxEffectsCpuLoad();
+        virtual uint32_t getMaxEffectsMemory();
+#ifdef AUDIO_POLICY_TEST
+        virtual     bool        threadLoop();
+                    void        exit();
+        int testOutputIndex(audio_io_handle_t output);
+#endif //AUDIO_POLICY_TEST
+
+        status_t setEffectEnabled(const sp<EffectDescriptor>& effectDesc, bool enabled);
+
+        SortedVector<audio_io_handle_t> getOutputsForDevice(audio_devices_t device,
+                        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs);
+        bool vectorsEqual(SortedVector<audio_io_handle_t>& outputs1,
+                                           SortedVector<audio_io_handle_t>& outputs2);
+
+        // mute/unmute strategies using an incompatible device combination
+        // if muting, wait for the audio in pcm buffer to be drained before proceeding
+        // if unmuting, unmute only after the specified delay
+        // Returns the number of ms waited
+        virtual uint32_t  checkDeviceMuteStrategies(sp<AudioOutputDescriptor> outputDesc,
+                                            audio_devices_t prevDevice,
+                                            uint32_t delayMs);
+
+        audio_io_handle_t selectOutput(const SortedVector<audio_io_handle_t>& outputs,
+                                       audio_output_flags_t flags,
+                                       audio_format_t format);
+        // samplingRate parameter is an in/out and so may be modified
+        sp<IOProfile> getInputProfile(audio_devices_t device,
+                                      String8 address,
+                                      uint32_t& samplingRate,
+                                      audio_format_t format,
+                                      audio_channel_mask_t channelMask,
+                                      audio_input_flags_t flags);
+        sp<IOProfile> getProfileForDirectOutput(audio_devices_t device,
+                                                       uint32_t samplingRate,
+                                                       audio_format_t format,
+                                                       audio_channel_mask_t channelMask,
+                                                       audio_output_flags_t flags);
+
+        audio_io_handle_t selectOutputForEffects(const SortedVector<audio_io_handle_t>& outputs);
+
+        bool isNonOffloadableEffectEnabled();
+
+        virtual status_t addAudioPatch(audio_patch_handle_t handle,
+                               const sp<AudioPatch>& patch);
+        virtual status_t removeAudioPatch(audio_patch_handle_t handle);
+
+        sp<AudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const;
+        sp<AudioInputDescriptor> getInputFromId(audio_port_handle_t id) const;
+        sp<HwModule> getModuleForDevice(audio_devices_t device) const;
+        sp<HwModule> getModuleFromName(const char *name) const;
+        audio_devices_t availablePrimaryOutputDevices();
+        audio_devices_t availablePrimaryInputDevices();
+
+        void updateCallRouting(audio_devices_t rxDevice, int delayMs = 0);
+
+
+        uid_t mUidCached;
+        AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
+        audio_io_handle_t mPrimaryOutput;              // primary output handle
+        // list of descriptors for outputs currently opened
+        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > mOutputs;
+        // copy of mOutputs before setDeviceConnectionState() opens new outputs
+        // reset to mOutputs when updateDevicesAndOutputs() is called.
+        DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > mPreviousOutputs;
+        DefaultKeyedVector<audio_io_handle_t, sp<AudioInputDescriptor> > mInputs;     // list of input descriptors
+        DeviceVector  mAvailableOutputDevices; // all available output devices
+        DeviceVector  mAvailableInputDevices;  // all available input devices
+        int mPhoneState;                                                    // current phone state
+        audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT];   // current forced use configuration
+
+        StreamDescriptor mStreams[AUDIO_STREAM_CNT];           // stream descriptors for volume control
+        bool    mLimitRingtoneVolume;                                       // limit ringtone volume to music volume if headset connected
+        audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
+        float   mLastVoiceVolume;                                           // last voice volume value sent to audio HAL
+
+        // Maximum CPU load allocated to audio effects in 0.1 MIPS (ARMv5TE, 0 WS memory) units
+        static const uint32_t MAX_EFFECTS_CPU_LOAD = 1000;
+        // Maximum memory allocated to audio effects in KB
+        static const uint32_t MAX_EFFECTS_MEMORY = 512;
+        uint32_t mTotalEffectsCpuLoad; // current CPU load used by effects
+        uint32_t mTotalEffectsMemory;  // current memory used by effects
+        KeyedVector<int, sp<EffectDescriptor> > mEffects;  // list of registered audio effects
+        bool    mA2dpSuspended;  // true if A2DP output is suspended
+        sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
+        bool mSpeakerDrcEnabled;// true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER path
+                                // to boost soft sounds, used to adjust volume curves accordingly
+
+        Vector < sp<HwModule> > mHwModules;
+        static volatile int32_t mNextUniqueId;
+        volatile int32_t mAudioPortGeneration;
+
+        DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> > mAudioPatches;
+
+        DefaultKeyedVector<audio_session_t, audio_io_handle_t> mSoundTriggerSessions;
+
+        sp<AudioPatch> mCallTxPatch;
+        sp<AudioPatch> mCallRxPatch;
+
+        // for supporting "beacon" streams, i.e. streams that only play on speaker, and never
+        // when something other than STREAM_TTS (a.k.a. "Transmitted Through Speaker") is playing
+        enum {
+            STARTING_OUTPUT,
+            STARTING_BEACON,
+            STOPPING_OUTPUT,
+            STOPPING_BEACON
+        };
+        uint32_t mBeaconMuteRefCount;   // ref count for stream that would mute beacon
+        uint32_t mBeaconPlayingRefCount;// ref count for the playing beacon streams
+        bool mBeaconMuted;              // has STREAM_TTS been muted
+
+        // custom mix entry in mPolicyMixes
+        class AudioPolicyMix : public RefBase {
+        public:
+            AudioPolicyMix() {}
+
+            AudioMix    mMix;                   // Audio policy mix descriptor
+            sp<AudioOutputDescriptor> mOutput;  // Corresponding output stream
+        };
+        DefaultKeyedVector<String8, sp<AudioPolicyMix> > mPolicyMixes; // list of registered mixes
+
+
+#ifdef AUDIO_POLICY_TEST
+        Mutex   mLock;
+        Condition mWaitWorkCV;
+
+        int             mCurOutput;
+        bool            mDirectOutput;
+        audio_io_handle_t mTestOutputs[NUM_TEST_OUTPUTS];
+        int             mTestInput;
+        uint32_t        mTestDevice;
+        uint32_t        mTestSamplingRate;
+        uint32_t        mTestFormat;
+        uint32_t        mTestChannels;
+        uint32_t        mTestLatencyMs;
+#endif //AUDIO_POLICY_TEST
+
+        static bool isVirtualInputDevice(audio_devices_t device);
+
+        uint32_t nextAudioPortGeneration();
+private:
+        // updates device caching and output for streams that can influence the
+        //    routing of notifications
+        void handleNotificationRoutingForStream(audio_stream_type_t stream);
+        static bool deviceDistinguishesOnAddress(audio_devices_t device);
+        // find the outputs on a given output descriptor that have the given address.
+        // to be called on an AudioOutputDescriptor whose supported devices (as defined
+        //   in mProfile->mSupportedDevices) matches the device whose address is to be matched.
+        // see deviceDistinguishesOnAddress(audio_devices_t) for whether the device type is one
+        //   where addresses are used to distinguish between one connected device and another.
+        void findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/,
+                const audio_devices_t device /*in*/,
+                const String8 address /*in*/,
+                SortedVector<audio_io_handle_t>& outputs /*out*/);
+        uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; }
+        // internal method to return the output handle for the given device and format
+        audio_io_handle_t getOutputForDevice(
+                audio_devices_t device,
+                audio_session_t session,
+                audio_stream_type_t stream,
+                uint32_t samplingRate,
+                audio_format_t format,
+                audio_channel_mask_t channelMask,
+                audio_output_flags_t flags,
+                const audio_offload_info_t *offloadInfo);
+        // internal function to derive a stream type value from audio attributes
+        audio_stream_type_t streamTypefromAttributesInt(const audio_attributes_t *attr);
+        // return true if any output is playing anything besides the stream to ignore
+        bool isAnyOutputActive(audio_stream_type_t streamToIgnore);
+        // event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON
+        // returns 0 if no mute/unmute event happened, the largest latency of the device where
+        //   the mute/unmute happened
+        uint32_t handleEventForBeacon(int event);
+        uint32_t setBeaconMute(bool mute);
+        bool     isValidAttributes(const audio_attributes_t *paa);
+
+        // select input device corresponding to requested audio source and return associated policy
+        // mix if any. Calls getDeviceForInputSource().
+        audio_devices_t getDeviceAndMixForInputSource(audio_source_t inputSource,
+                                                        AudioMix **policyMix = NULL);
+
+        // Called by setDeviceConnectionState().
+        status_t setDeviceConnectionStateInt(audio_devices_t device,
+                                                          audio_policy_dev_state_t state,
+                                                          const char *device_address,
+                                                          const char *device_name);
+        sp<DeviceDescriptor>  getDeviceDescriptor(const audio_devices_t device,
+                                                  const char *device_address,
+                                                  const char *device_name);
+};
+
+};
diff --git a/services/audiopolicy/managerdefault/ConfigParsingUtils.cpp b/services/audiopolicy/managerdefault/ConfigParsingUtils.cpp
new file mode 100644
index 0000000..1afd487
--- /dev/null
+++ b/services/audiopolicy/managerdefault/ConfigParsingUtils.cpp
@@ -0,0 +1,121 @@
+/*
+ * 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 "APM::ConfigParsingUtils"
+//#define LOG_NDEBUG 0
+
+#include "AudioPolicyManager.h"
+
+namespace android {
+
+//static
+uint32_t ConfigParsingUtils::stringToEnum(const struct StringToEnum *table,
+                                              size_t size,
+                                              const char *name)
+{
+    for (size_t i = 0; i < size; i++) {
+        if (strcmp(table[i].name, name) == 0) {
+            ALOGV("stringToEnum() found %s", table[i].name);
+            return table[i].value;
+        }
+    }
+    return 0;
+}
+
+//static
+const char *ConfigParsingUtils::enumToString(const struct StringToEnum *table,
+                                              size_t size,
+                                              uint32_t value)
+{
+    for (size_t i = 0; i < size; i++) {
+        if (table[i].value == value) {
+            return table[i].name;
+        }
+    }
+    return "";
+}
+
+//static
+bool ConfigParsingUtils::stringToBool(const char *value)
+{
+    return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0));
+}
+
+
+// --- audio_policy.conf file parsing
+//static
+uint32_t ConfigParsingUtils::parseOutputFlagNames(char *name)
+{
+    uint32_t flag = 0;
+
+    // it is OK to cast name to non const here as we are not going to use it after
+    // strtok() modifies it
+    char *flagName = strtok(name, "|");
+    while (flagName != NULL) {
+        if (strlen(flagName) != 0) {
+            flag |= ConfigParsingUtils::stringToEnum(sOutputFlagNameToEnumTable,
+                               ARRAY_SIZE(sOutputFlagNameToEnumTable),
+                               flagName);
+        }
+        flagName = strtok(NULL, "|");
+    }
+    //force direct flag if offload flag is set: offloading implies a direct output stream
+    // and all common behaviors are driven by checking only the direct flag
+    // this should normally be set appropriately in the policy configuration file
+    if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+        flag |= AUDIO_OUTPUT_FLAG_DIRECT;
+    }
+
+    return flag;
+}
+
+//static
+uint32_t ConfigParsingUtils::parseInputFlagNames(char *name)
+{
+    uint32_t flag = 0;
+
+    // it is OK to cast name to non const here as we are not going to use it after
+    // strtok() modifies it
+    char *flagName = strtok(name, "|");
+    while (flagName != NULL) {
+        if (strlen(flagName) != 0) {
+            flag |= stringToEnum(sInputFlagNameToEnumTable,
+                               ARRAY_SIZE(sInputFlagNameToEnumTable),
+                               flagName);
+        }
+        flagName = strtok(NULL, "|");
+    }
+    return flag;
+}
+
+//static
+audio_devices_t ConfigParsingUtils::parseDeviceNames(char *name)
+{
+    uint32_t device = 0;
+
+    char *devName = strtok(name, "|");
+    while (devName != NULL) {
+        if (strlen(devName) != 0) {
+            device |= stringToEnum(sDeviceNameToEnumTable,
+                                 ARRAY_SIZE(sDeviceNameToEnumTable),
+                                 devName);
+         }
+        devName = strtok(NULL, "|");
+     }
+    return device;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/ConfigParsingUtils.h b/services/audiopolicy/managerdefault/ConfigParsingUtils.h
new file mode 100644
index 0000000..b2d9763
--- /dev/null
+++ b/services/audiopolicy/managerdefault/ConfigParsingUtils.h
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+// Definitions for audio_policy.conf file parsing
+// ----------------------------------------------------------------------------
+
+struct StringToEnum {
+    const char *name;
+    uint32_t value;
+};
+
+#define STRING_TO_ENUM(string) { #string, string }
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+const StringToEnum sDeviceNameToEnumTable[] = {
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_EARPIECE),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPEAKER_SAFE),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADSET),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_SCO),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_A2DP),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_DIGITAL),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_ACCESSORY),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_USB_DEVICE),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_ALL_USB),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_REMOTE_SUBMIX),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_TELEPHONY_TX),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_LINE),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_HDMI_ARC),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM),
+    STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_AMBIENT),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_ALL_SCO),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_HDMI),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_USB_DEVICE),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_FM_TUNER),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_LINE),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_SPDIF),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
+};
+
+const StringToEnum sOutputFlagNameToEnumTable[] = {
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
+    STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
+};
+
+const StringToEnum sInputFlagNameToEnumTable[] = {
+    STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
+    STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
+};
+
+const StringToEnum sFormatNameToEnumTable[] = {
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_FLOAT),
+    STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
+    STRING_TO_ENUM(AUDIO_FORMAT_MP3),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_MAIN),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_LC),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_SSR),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_LTP),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V1),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_SCALABLE),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_ERLC),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_LD),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_HE_V2),
+    STRING_TO_ENUM(AUDIO_FORMAT_AAC_ELD),
+    STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
+    STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V1),
+    STRING_TO_ENUM(AUDIO_FORMAT_HE_AAC_V2),
+    STRING_TO_ENUM(AUDIO_FORMAT_OPUS),
+    STRING_TO_ENUM(AUDIO_FORMAT_AC3),
+    STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
+};
+
+const StringToEnum sOutChannelsNameToEnumTable[] = {
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_MONO),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
+    STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
+};
+
+const StringToEnum sInChannelsNameToEnumTable[] = {
+    STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
+    STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
+    STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
+};
+
+const StringToEnum sGainModeNameToEnumTable[] = {
+    STRING_TO_ENUM(AUDIO_GAIN_MODE_JOINT),
+    STRING_TO_ENUM(AUDIO_GAIN_MODE_CHANNELS),
+    STRING_TO_ENUM(AUDIO_GAIN_MODE_RAMP),
+};
+
+class ConfigParsingUtils
+{
+public:
+    static uint32_t stringToEnum(const struct StringToEnum *table,
+            size_t size,
+            const char *name);
+    static const char *enumToString(const struct StringToEnum *table,
+            size_t size,
+            uint32_t value);
+    static bool stringToBool(const char *value);
+    static uint32_t parseOutputFlagNames(char *name);
+    static uint32_t parseInputFlagNames(char *name);
+    static audio_devices_t parseDeviceNames(char *name);
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Devices.cpp b/services/audiopolicy/managerdefault/Devices.cpp
new file mode 100644
index 0000000..13c8bbc
--- /dev/null
+++ b/services/audiopolicy/managerdefault/Devices.cpp
@@ -0,0 +1,282 @@
+/*
+ * 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 "APM::Devices"
+//#define LOG_NDEBUG 0
+
+#include "AudioPolicyManager.h"
+
+namespace android {
+
+String8 DeviceDescriptor::emptyNameStr = String8("");
+
+DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) :
+                     AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
+                               audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
+                                                              AUDIO_PORT_ROLE_SOURCE,
+                             NULL),
+                     mDeviceType(type), mAddress("")
+{
+
+}
+
+bool DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
+{
+    // Devices are considered equal if they:
+    // - are of the same type (a device type cannot be AUDIO_DEVICE_NONE)
+    // - have the same address or one device does not specify the address
+    // - have the same channel mask or one device does not specify the channel mask
+    return (mDeviceType == other->mDeviceType) &&
+           (mAddress == "" || other->mAddress == "" || mAddress == other->mAddress) &&
+           (mChannelMask == 0 || other->mChannelMask == 0 ||
+                mChannelMask == other->mChannelMask);
+}
+
+void DeviceDescriptor::loadGains(cnode *root)
+{
+    AudioPort::loadGains(root);
+    if (mGains.size() > 0) {
+        mGains[0]->getDefaultConfig(&mGain);
+    }
+}
+
+void DeviceVector::refreshTypes()
+{
+    mDeviceTypes = AUDIO_DEVICE_NONE;
+    for(size_t i = 0; i < size(); i++) {
+        mDeviceTypes |= itemAt(i)->mDeviceType;
+    }
+    ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
+}
+
+ssize_t DeviceVector::indexOf(const sp<DeviceDescriptor>& item) const
+{
+    for(size_t i = 0; i < size(); i++) {
+        if (item->equals(itemAt(i))) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+ssize_t DeviceVector::add(const sp<DeviceDescriptor>& item)
+{
+    ssize_t ret = indexOf(item);
+
+    if (ret < 0) {
+        ret = SortedVector::add(item);
+        if (ret >= 0) {
+            refreshTypes();
+        }
+    } else {
+        ALOGW("DeviceVector::add device %08x already in", item->mDeviceType);
+        ret = -1;
+    }
+    return ret;
+}
+
+ssize_t DeviceVector::remove(const sp<DeviceDescriptor>& item)
+{
+    size_t i;
+    ssize_t ret = indexOf(item);
+
+    if (ret < 0) {
+        ALOGW("DeviceVector::remove device %08x not in", item->mDeviceType);
+    } else {
+        ret = SortedVector::removeAt(ret);
+        if (ret >= 0) {
+            refreshTypes();
+        }
+    }
+    return ret;
+}
+
+void DeviceVector::loadDevicesFromType(audio_devices_t types)
+{
+    DeviceVector deviceList;
+
+    uint32_t role_bit = AUDIO_DEVICE_BIT_IN & types;
+    types &= ~role_bit;
+
+    while (types) {
+        uint32_t i = 31 - __builtin_clz(types);
+        uint32_t type = 1 << i;
+        types &= ~type;
+        add(new DeviceDescriptor(String8("device_type"), type | role_bit));
+    }
+}
+
+void DeviceVector::loadDevicesFromName(char *name,
+                                       const DeviceVector& declaredDevices)
+{
+    char *devName = strtok(name, "|");
+    while (devName != NULL) {
+        if (strlen(devName) != 0) {
+            audio_devices_t type = ConfigParsingUtils::stringToEnum(sDeviceNameToEnumTable,
+                                 ARRAY_SIZE(sDeviceNameToEnumTable),
+                                 devName);
+            if (type != AUDIO_DEVICE_NONE) {
+                sp<DeviceDescriptor> dev = new DeviceDescriptor(String8(name), type);
+                if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX ||
+                        type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
+                    dev->mAddress = String8("0");
+                }
+                add(dev);
+            } else {
+                sp<DeviceDescriptor> deviceDesc =
+                        declaredDevices.getDeviceFromName(String8(devName));
+                if (deviceDesc != 0) {
+                    add(deviceDesc);
+                }
+            }
+         }
+         devName = strtok(NULL, "|");
+     }
+}
+
+sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, String8 address) const
+{
+    sp<DeviceDescriptor> device;
+    for (size_t i = 0; i < size(); i++) {
+        if (itemAt(i)->mDeviceType == type) {
+            if (address == "" || itemAt(i)->mAddress == address) {
+                device = itemAt(i);
+                if (itemAt(i)->mAddress == address) {
+                    break;
+                }
+            }
+        }
+    }
+    ALOGV("DeviceVector::getDevice() for type %08x address %s found %p",
+          type, address.string(), device.get());
+    return device;
+}
+
+sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
+{
+    sp<DeviceDescriptor> device;
+    for (size_t i = 0; i < size(); i++) {
+        if (itemAt(i)->getHandle() == id) {
+            device = itemAt(i);
+            break;
+        }
+    }
+    return device;
+}
+
+DeviceVector DeviceVector::getDevicesFromType(audio_devices_t type) const
+{
+    DeviceVector devices;
+    for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
+        if (itemAt(i)->mDeviceType & type & ~AUDIO_DEVICE_BIT_IN) {
+            devices.add(itemAt(i));
+            type &= ~itemAt(i)->mDeviceType;
+            ALOGV("DeviceVector::getDevicesFromType() for type %x found %p",
+                  itemAt(i)->mDeviceType, itemAt(i).get());
+        }
+    }
+    return devices;
+}
+
+DeviceVector DeviceVector::getDevicesFromTypeAddr(
+        audio_devices_t type, String8 address) const
+{
+    DeviceVector devices;
+    for (size_t i = 0; i < size(); i++) {
+        if (itemAt(i)->mDeviceType == type) {
+            if (itemAt(i)->mAddress == address) {
+                devices.add(itemAt(i));
+            }
+        }
+    }
+    return devices;
+}
+
+sp<DeviceDescriptor> DeviceVector::getDeviceFromName(const String8& name) const
+{
+    sp<DeviceDescriptor> device;
+    for (size_t i = 0; i < size(); i++) {
+        if (itemAt(i)->mName == name) {
+            device = itemAt(i);
+            break;
+        }
+    }
+    return device;
+}
+
+void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
+                                         const struct audio_port_config *srcConfig) const
+{
+    dstConfig->config_mask = AUDIO_PORT_CONFIG_CHANNEL_MASK|AUDIO_PORT_CONFIG_GAIN;
+    if (srcConfig != NULL) {
+        dstConfig->config_mask |= srcConfig->config_mask;
+    }
+
+    AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
+
+    dstConfig->id = mId;
+    dstConfig->role = audio_is_output_device(mDeviceType) ?
+                        AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
+    dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
+    dstConfig->ext.device.type = mDeviceType;
+
+    //TODO Understand why this test is necessary. i.e. why at boot time does it crash
+    // without the test?
+    // This has been demonstrated to NOT be true (at start up)
+    // ALOG_ASSERT(mModule != NULL);
+    dstConfig->ext.device.hw_module = mModule != NULL ? mModule->mHandle : NULL;
+    strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
+}
+
+void DeviceDescriptor::toAudioPort(struct audio_port *port) const
+{
+    ALOGV("DeviceDescriptor::toAudioPort() handle %d type %x", mId, mDeviceType);
+    AudioPort::toAudioPort(port);
+    port->id = mId;
+    toAudioPortConfig(&port->active_config);
+    port->ext.device.type = mDeviceType;
+    port->ext.device.hw_module = mModule->mHandle;
+    strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
+}
+
+status_t DeviceDescriptor::dump(int fd, int spaces, int index) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "%*sDevice %d:\n", spaces, "", index+1);
+    result.append(buffer);
+    if (mId != 0) {
+        snprintf(buffer, SIZE, "%*s- id: %2d\n", spaces, "", mId);
+        result.append(buffer);
+    }
+    snprintf(buffer, SIZE, "%*s- type: %-48s\n", spaces, "",
+            ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
+                    ARRAY_SIZE(sDeviceNameToEnumTable),
+                    mDeviceType));
+    result.append(buffer);
+    if (mAddress.size() != 0) {
+        snprintf(buffer, SIZE, "%*s- address: %-32s\n", spaces, "", mAddress.string());
+        result.append(buffer);
+    }
+    write(fd, result.string(), result.size());
+    AudioPort::dump(fd, spaces);
+
+    return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Devices.h b/services/audiopolicy/managerdefault/Devices.h
new file mode 100644
index 0000000..af2fbda
--- /dev/null
+++ b/services/audiopolicy/managerdefault/Devices.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+namespace android {
+
+class AudioPort;
+class AudioPortConfig;
+
+class DeviceDescriptor: public AudioPort, public AudioPortConfig
+{
+public:
+    DeviceDescriptor(const String8& name, audio_devices_t type);
+
+    virtual ~DeviceDescriptor() {}
+
+    bool equals(const sp<DeviceDescriptor>& other) const;
+
+    // AudioPortConfig
+    virtual sp<AudioPort> getAudioPort() const { return (AudioPort*) this; }
+    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
+            const struct audio_port_config *srcConfig = NULL) const;
+
+    // AudioPort
+    virtual void loadGains(cnode *root);
+    virtual void toAudioPort(struct audio_port *port) const;
+
+    status_t dump(int fd, int spaces, int index) const;
+
+    audio_devices_t mDeviceType;
+    String8 mAddress;
+
+    static String8  emptyNameStr;
+};
+
+class DeviceVector : public SortedVector< sp<DeviceDescriptor> >
+{
+public:
+    DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
+
+    ssize_t         add(const sp<DeviceDescriptor>& item);
+    ssize_t         remove(const sp<DeviceDescriptor>& item);
+    ssize_t         indexOf(const sp<DeviceDescriptor>& item) const;
+
+    audio_devices_t types() const { return mDeviceTypes; }
+
+    void loadDevicesFromType(audio_devices_t types);
+    void loadDevicesFromName(char *name, const DeviceVector& declaredDevices);
+
+    sp<DeviceDescriptor> getDevice(audio_devices_t type, String8 address) const;
+    DeviceVector getDevicesFromType(audio_devices_t types) const;
+    sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
+    sp<DeviceDescriptor> getDeviceFromName(const String8& name) const;
+    DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address)
+    const;
+
+private:
+    void refreshTypes();
+    audio_devices_t mDeviceTypes;
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Gains.cpp b/services/audiopolicy/managerdefault/Gains.cpp
new file mode 100644
index 0000000..4aca26d
--- /dev/null
+++ b/services/audiopolicy/managerdefault/Gains.cpp
@@ -0,0 +1,446 @@
+/*
+ * 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 "APM::Gains"
+//#define LOG_NDEBUG 0
+
+//#define VERY_VERBOSE_LOGGING
+#ifdef VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
+
+#include "AudioPolicyManager.h"
+
+#include <math.h>
+
+namespace android {
+
+const VolumeCurvePoint
+ApmGains::sDefaultVolumeCurve[ApmGains::VOLCNT] = {
+    {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}
+};
+
+
+const VolumeCurvePoint
+ApmGains::sDefaultMediaVolumeCurve[ApmGains::VOLCNT] = {
+    {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sExtMediaSystemVolumeCurve[ApmGains::VOLCNT] = {
+    {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sSpeakerMediaVolumeCurve[ApmGains::VOLCNT] = {
+    {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT] = {
+    {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT] = {
+    {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT] = {
+    {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f}
+};
+
+// AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks
+// AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets.
+// AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java).
+// The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset.
+
+const VolumeCurvePoint
+ApmGains::sDefaultSystemVolumeCurve[ApmGains::VOLCNT] = {
+    {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT] = {
+    {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sHeadsetSystemVolumeCurve[ApmGains::VOLCNT] = {
+    {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sDefaultVoiceVolumeCurve[ApmGains::VOLCNT] = {
+    {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT] = {
+    {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sLinearVolumeCurve[ApmGains::VOLCNT] = {
+    {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sSilentVolumeCurve[ApmGains::VOLCNT] = {
+    {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f}
+};
+
+const VolumeCurvePoint
+ApmGains::sFullScaleVolumeCurve[ApmGains::VOLCNT] = {
+    {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint *ApmGains::sVolumeProfiles[AUDIO_STREAM_CNT]
+                                                  [ApmGains::DEVICE_CATEGORY_CNT] = {
+    { // AUDIO_STREAM_VOICE_CALL
+        ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_SYSTEM
+        ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sDefaultSystemVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_RING
+        ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_MUSIC
+        ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_ALARM
+        ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_NOTIFICATION
+        ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sDefaultVolumeCurve,  // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_BLUETOOTH_SCO
+        ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_ENFORCED_AUDIBLE
+        ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    {  // AUDIO_STREAM_DTMF
+        ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sExtMediaSystemVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_TTS
+      // "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER
+        ApmGains::sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sLinearVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sSilentVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_ACCESSIBILITY
+        ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_REROUTING
+        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sFullScaleVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+    { // AUDIO_STREAM_PATCH
+        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
+        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+        ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+        ApmGains::sFullScaleVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
+    },
+};
+
+//static
+audio_devices_t ApmGains::getDeviceForVolume(audio_devices_t device)
+{
+    if (device == AUDIO_DEVICE_NONE) {
+        // this happens when forcing a route update and no track is active on an output.
+        // In this case the returned category is not important.
+        device =  AUDIO_DEVICE_OUT_SPEAKER;
+    } else if (popcount(device) > 1) {
+        // Multiple device selection is either:
+        //  - speaker + one other device: give priority to speaker in this case.
+        //  - one A2DP device + another device: happens with duplicated output. In this case
+        // retain the device on the A2DP output as the other must not correspond to an active
+        // selection if not the speaker.
+        //  - HDMI-CEC system audio mode only output: give priority to available item in order.
+        if (device & AUDIO_DEVICE_OUT_SPEAKER) {
+            device = AUDIO_DEVICE_OUT_SPEAKER;
+        } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
+            device = AUDIO_DEVICE_OUT_HDMI_ARC;
+        } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
+            device = AUDIO_DEVICE_OUT_AUX_LINE;
+        } else if (device & AUDIO_DEVICE_OUT_SPDIF) {
+            device = AUDIO_DEVICE_OUT_SPDIF;
+        } else {
+            device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
+        }
+    }
+
+    /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
+    if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
+        device = AUDIO_DEVICE_OUT_SPEAKER;
+
+    ALOGW_IF(popcount(device) != 1,
+            "getDeviceForVolume() invalid device combination: %08x",
+            device);
+
+    return device;
+}
+
+//static
+ApmGains::device_category ApmGains::getDeviceCategory(audio_devices_t device)
+{
+    switch(getDeviceForVolume(device)) {
+        case AUDIO_DEVICE_OUT_EARPIECE:
+            return ApmGains::DEVICE_CATEGORY_EARPIECE;
+        case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+        case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+            return ApmGains::DEVICE_CATEGORY_HEADSET;
+        case AUDIO_DEVICE_OUT_LINE:
+        case AUDIO_DEVICE_OUT_AUX_DIGITAL:
+        /*USB?  Remote submix?*/
+            return ApmGains::DEVICE_CATEGORY_EXT_MEDIA;
+        case AUDIO_DEVICE_OUT_SPEAKER:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+        case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+        case AUDIO_DEVICE_OUT_USB_ACCESSORY:
+        case AUDIO_DEVICE_OUT_USB_DEVICE:
+        case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
+        default:
+            return ApmGains::DEVICE_CATEGORY_SPEAKER;
+    }
+}
+
+//static
+float ApmGains::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
+        int indexInUi)
+{
+    ApmGains::device_category deviceCategory = ApmGains::getDeviceCategory(device);
+    const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory];
+
+    // the volume index in the UI is relative to the min and max volume indices for this stream type
+    int nbSteps = 1 + curve[ApmGains::VOLMAX].mIndex -
+            curve[ApmGains::VOLMIN].mIndex;
+    int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /
+            (streamDesc.mIndexMax - streamDesc.mIndexMin);
+
+    // find what part of the curve this index volume belongs to, or if it's out of bounds
+    int segment = 0;
+    if (volIdx < curve[ApmGains::VOLMIN].mIndex) {         // out of bounds
+        return 0.0f;
+    } else if (volIdx < curve[ApmGains::VOLKNEE1].mIndex) {
+        segment = 0;
+    } else if (volIdx < curve[ApmGains::VOLKNEE2].mIndex) {
+        segment = 1;
+    } else if (volIdx <= curve[ApmGains::VOLMAX].mIndex) {
+        segment = 2;
+    } else {                                                               // out of bounds
+        return 1.0f;
+    }
+
+    // linear interpolation in the attenuation table in dB
+    float decibels = curve[segment].mDBAttenuation +
+            ((float)(volIdx - curve[segment].mIndex)) *
+                ( (curve[segment+1].mDBAttenuation -
+                        curve[segment].mDBAttenuation) /
+                    ((float)(curve[segment+1].mIndex -
+                            curve[segment].mIndex)) );
+
+    float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )
+
+    ALOGVV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f",
+            curve[segment].mIndex, volIdx,
+            curve[segment+1].mIndex,
+            curve[segment].mDBAttenuation,
+            decibels,
+            curve[segment+1].mDBAttenuation,
+            amplification);
+
+    return amplification;
+}
+
+
+
+AudioGain::AudioGain(int index, bool useInChannelMask)
+{
+    mIndex = index;
+    mUseInChannelMask = useInChannelMask;
+    memset(&mGain, 0, sizeof(struct audio_gain));
+}
+
+void AudioGain::getDefaultConfig(struct audio_gain_config *config)
+{
+    config->index = mIndex;
+    config->mode = mGain.mode;
+    config->channel_mask = mGain.channel_mask;
+    if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
+        config->values[0] = mGain.default_value;
+    } else {
+        uint32_t numValues;
+        if (mUseInChannelMask) {
+            numValues = audio_channel_count_from_in_mask(mGain.channel_mask);
+        } else {
+            numValues = audio_channel_count_from_out_mask(mGain.channel_mask);
+        }
+        for (size_t i = 0; i < numValues; i++) {
+            config->values[i] = mGain.default_value;
+        }
+    }
+    if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
+        config->ramp_duration_ms = mGain.min_ramp_ms;
+    }
+}
+
+status_t AudioGain::checkConfig(const struct audio_gain_config *config)
+{
+    if ((config->mode & ~mGain.mode) != 0) {
+        return BAD_VALUE;
+    }
+    if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
+        if ((config->values[0] < mGain.min_value) ||
+                    (config->values[0] > mGain.max_value)) {
+            return BAD_VALUE;
+        }
+    } else {
+        if ((config->channel_mask & ~mGain.channel_mask) != 0) {
+            return BAD_VALUE;
+        }
+        uint32_t numValues;
+        if (mUseInChannelMask) {
+            numValues = audio_channel_count_from_in_mask(config->channel_mask);
+        } else {
+            numValues = audio_channel_count_from_out_mask(config->channel_mask);
+        }
+        for (size_t i = 0; i < numValues; i++) {
+            if ((config->values[i] < mGain.min_value) ||
+                    (config->values[i] > mGain.max_value)) {
+                return BAD_VALUE;
+            }
+        }
+    }
+    if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
+        if ((config->ramp_duration_ms < mGain.min_ramp_ms) ||
+                    (config->ramp_duration_ms > mGain.max_ramp_ms)) {
+            return BAD_VALUE;
+        }
+    }
+    return NO_ERROR;
+}
+
+void AudioGain::dump(int fd, int spaces, int index) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms);
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+}
+
+
+// --- StreamDescriptor class implementation
+
+StreamDescriptor::StreamDescriptor()
+    :   mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
+{
+    mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
+}
+
+int StreamDescriptor::getVolumeIndex(audio_devices_t device)
+{
+    device = ApmGains::getDeviceForVolume(device);
+    // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
+    if (mIndexCur.indexOfKey(device) < 0) {
+        device = AUDIO_DEVICE_OUT_DEFAULT;
+    }
+    return mIndexCur.valueFor(device);
+}
+
+void StreamDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "%s         %02d         %02d         ",
+             mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
+    result.append(buffer);
+    for (size_t i = 0; i < mIndexCur.size(); i++) {
+        snprintf(buffer, SIZE, "%04x : %02d, ",
+                 mIndexCur.keyAt(i),
+                 mIndexCur.valueAt(i));
+        result.append(buffer);
+    }
+    result.append("\n");
+
+    write(fd, result.string(), result.size());
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Gains.h b/services/audiopolicy/managerdefault/Gains.h
new file mode 100644
index 0000000..b4ab129
--- /dev/null
+++ b/services/audiopolicy/managerdefault/Gains.h
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+namespace android {
+
+class VolumeCurvePoint
+{
+public:
+    int mIndex;
+    float mDBAttenuation;
+};
+
+class StreamDescriptor;
+
+class ApmGains
+{
+public :
+    // 4 points to define the volume attenuation curve, each characterized by the volume
+    // index (from 0 to 100) at which they apply, and the attenuation in dB at that index.
+    // we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl()
+    enum { VOLMIN = 0, VOLKNEE1 = 1, VOLKNEE2 = 2, VOLMAX = 3, VOLCNT = 4};
+
+    // device categories used for volume curve management.
+    enum device_category {
+        DEVICE_CATEGORY_HEADSET,
+        DEVICE_CATEGORY_SPEAKER,
+        DEVICE_CATEGORY_EARPIECE,
+        DEVICE_CATEGORY_EXT_MEDIA,
+        DEVICE_CATEGORY_CNT
+    };
+
+    // returns the category the device belongs to with regard to volume curve management
+    static ApmGains::device_category getDeviceCategory(audio_devices_t device);
+
+    // extract one device relevant for volume control from multiple device selection
+    static audio_devices_t getDeviceForVolume(audio_devices_t device);
+
+    static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
+                    int indexInUi);
+
+    // default volume curve
+    static const VolumeCurvePoint sDefaultVolumeCurve[ApmGains::VOLCNT];
+    // default volume curve for media strategy
+    static const VolumeCurvePoint sDefaultMediaVolumeCurve[ApmGains::VOLCNT];
+    // volume curve for non-media audio on ext media outputs (HDMI, Line, etc)
+    static const VolumeCurvePoint sExtMediaSystemVolumeCurve[ApmGains::VOLCNT];
+    // volume curve for media strategy on speakers
+    static const VolumeCurvePoint sSpeakerMediaVolumeCurve[ApmGains::VOLCNT];
+    static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT];
+    // volume curve for sonification strategy on speakers
+    static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT];
+    static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT];
+    static const VolumeCurvePoint sDefaultSystemVolumeCurve[ApmGains::VOLCNT];
+    static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT];
+    static const VolumeCurvePoint sHeadsetSystemVolumeCurve[ApmGains::VOLCNT];
+    static const VolumeCurvePoint sDefaultVoiceVolumeCurve[ApmGains::VOLCNT];
+    static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT];
+    static const VolumeCurvePoint sLinearVolumeCurve[ApmGains::VOLCNT];
+    static const VolumeCurvePoint sSilentVolumeCurve[ApmGains::VOLCNT];
+    static const VolumeCurvePoint sFullScaleVolumeCurve[ApmGains::VOLCNT];
+    // default volume curves per stream and device category. See initializeVolumeCurves()
+    static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][ApmGains::DEVICE_CATEGORY_CNT];
+};
+
+
+class AudioGain: public RefBase
+{
+public:
+    AudioGain(int index, bool useInChannelMask);
+    virtual ~AudioGain() {}
+
+    void dump(int fd, int spaces, int index) const;
+
+    void getDefaultConfig(struct audio_gain_config *config);
+    status_t checkConfig(const struct audio_gain_config *config);
+    int               mIndex;
+    struct audio_gain mGain;
+    bool              mUseInChannelMask;
+};
+
+
+// stream descriptor used for volume control
+class StreamDescriptor
+{
+public:
+    StreamDescriptor();
+
+    int getVolumeIndex(audio_devices_t device);
+    void dump(int fd);
+
+    int mIndexMin;      // min volume index
+    int mIndexMax;      // max volume index
+    KeyedVector<audio_devices_t, int> mIndexCur;   // current volume index per device
+    bool mCanBeMuted;   // true is the stream can be muted
+
+    const VolumeCurvePoint *mVolumeCurve[ApmGains::DEVICE_CATEGORY_CNT];
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/HwModule.cpp b/services/audiopolicy/managerdefault/HwModule.cpp
new file mode 100644
index 0000000..a04bdc8
--- /dev/null
+++ b/services/audiopolicy/managerdefault/HwModule.cpp
@@ -0,0 +1,279 @@
+/*
+ * 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 "APM::HwModule"
+//#define LOG_NDEBUG 0
+
+#include "AudioPolicyManager.h"
+#include "audio_policy_conf.h"
+#include <hardware/audio.h>
+
+namespace android {
+
+HwModule::HwModule(const char *name)
+    : mName(strndup(name, AUDIO_HARDWARE_MODULE_ID_MAX_LEN)),
+      mHalVersion(AUDIO_DEVICE_API_VERSION_MIN), mHandle(0)
+{
+}
+
+HwModule::~HwModule()
+{
+    for (size_t i = 0; i < mOutputProfiles.size(); i++) {
+        mOutputProfiles[i]->mSupportedDevices.clear();
+    }
+    for (size_t i = 0; i < mInputProfiles.size(); i++) {
+        mInputProfiles[i]->mSupportedDevices.clear();
+    }
+    free((void *)mName);
+}
+
+status_t HwModule::loadInput(cnode *root)
+{
+    cnode *node = root->first_child;
+
+    sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SINK, this);
+
+    while (node) {
+        if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
+            profile->loadSamplingRates((char *)node->value);
+        } else if (strcmp(node->name, FORMATS_TAG) == 0) {
+            profile->loadFormats((char *)node->value);
+        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
+            profile->loadInChannels((char *)node->value);
+        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
+            profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
+                                                           mDeclaredDevices);
+        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
+            profile->mFlags = ConfigParsingUtils::parseInputFlagNames((char *)node->value);
+        } else if (strcmp(node->name, GAINS_TAG) == 0) {
+            profile->loadGains(node);
+        }
+        node = node->next;
+    }
+    ALOGW_IF(profile->mSupportedDevices.isEmpty(),
+            "loadInput() invalid supported devices");
+    ALOGW_IF(profile->mChannelMasks.size() == 0,
+            "loadInput() invalid supported channel masks");
+    ALOGW_IF(profile->mSamplingRates.size() == 0,
+            "loadInput() invalid supported sampling rates");
+    ALOGW_IF(profile->mFormats.size() == 0,
+            "loadInput() invalid supported formats");
+    if (!profile->mSupportedDevices.isEmpty() &&
+            (profile->mChannelMasks.size() != 0) &&
+            (profile->mSamplingRates.size() != 0) &&
+            (profile->mFormats.size() != 0)) {
+
+        ALOGV("loadInput() adding input Supported Devices %04x",
+              profile->mSupportedDevices.types());
+
+        mInputProfiles.add(profile);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t HwModule::loadOutput(cnode *root)
+{
+    cnode *node = root->first_child;
+
+    sp<IOProfile> profile = new IOProfile(String8(root->name), AUDIO_PORT_ROLE_SOURCE, this);
+
+    while (node) {
+        if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
+            profile->loadSamplingRates((char *)node->value);
+        } else if (strcmp(node->name, FORMATS_TAG) == 0) {
+            profile->loadFormats((char *)node->value);
+        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
+            profile->loadOutChannels((char *)node->value);
+        } else if (strcmp(node->name, DEVICES_TAG) == 0) {
+            profile->mSupportedDevices.loadDevicesFromName((char *)node->value,
+                                                           mDeclaredDevices);
+        } else if (strcmp(node->name, FLAGS_TAG) == 0) {
+            profile->mFlags = ConfigParsingUtils::parseOutputFlagNames((char *)node->value);
+        } else if (strcmp(node->name, GAINS_TAG) == 0) {
+            profile->loadGains(node);
+        }
+        node = node->next;
+    }
+    ALOGW_IF(profile->mSupportedDevices.isEmpty(),
+            "loadOutput() invalid supported devices");
+    ALOGW_IF(profile->mChannelMasks.size() == 0,
+            "loadOutput() invalid supported channel masks");
+    ALOGW_IF(profile->mSamplingRates.size() == 0,
+            "loadOutput() invalid supported sampling rates");
+    ALOGW_IF(profile->mFormats.size() == 0,
+            "loadOutput() invalid supported formats");
+    if (!profile->mSupportedDevices.isEmpty() &&
+            (profile->mChannelMasks.size() != 0) &&
+            (profile->mSamplingRates.size() != 0) &&
+            (profile->mFormats.size() != 0)) {
+
+        ALOGV("loadOutput() adding output Supported Devices %04x, mFlags %04x",
+              profile->mSupportedDevices.types(), profile->mFlags);
+
+        mOutputProfiles.add(profile);
+        return NO_ERROR;
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+status_t HwModule::loadDevice(cnode *root)
+{
+    cnode *node = root->first_child;
+
+    audio_devices_t type = AUDIO_DEVICE_NONE;
+    while (node) {
+        if (strcmp(node->name, DEVICE_TYPE) == 0) {
+            type = ConfigParsingUtils::parseDeviceNames((char *)node->value);
+            break;
+        }
+        node = node->next;
+    }
+    if (type == AUDIO_DEVICE_NONE ||
+            (!audio_is_input_device(type) && !audio_is_output_device(type))) {
+        ALOGW("loadDevice() bad type %08x", type);
+        return BAD_VALUE;
+    }
+    sp<DeviceDescriptor> deviceDesc = new DeviceDescriptor(String8(root->name), type);
+    deviceDesc->mModule = this;
+
+    node = root->first_child;
+    while (node) {
+        if (strcmp(node->name, DEVICE_ADDRESS) == 0) {
+            deviceDesc->mAddress = String8((char *)node->value);
+        } else if (strcmp(node->name, CHANNELS_TAG) == 0) {
+            if (audio_is_input_device(type)) {
+                deviceDesc->loadInChannels((char *)node->value);
+            } else {
+                deviceDesc->loadOutChannels((char *)node->value);
+            }
+        } else if (strcmp(node->name, GAINS_TAG) == 0) {
+            deviceDesc->loadGains(node);
+        }
+        node = node->next;
+    }
+
+    ALOGV("loadDevice() adding device name %s type %08x address %s",
+          deviceDesc->mName.string(), type, deviceDesc->mAddress.string());
+
+    mDeclaredDevices.add(deviceDesc);
+
+    return NO_ERROR;
+}
+
+status_t HwModule::addOutputProfile(String8 name, const audio_config_t *config,
+                                                  audio_devices_t device, String8 address)
+{
+    sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SOURCE, this);
+
+    profile->mSamplingRates.add(config->sample_rate);
+    profile->mChannelMasks.add(config->channel_mask);
+    profile->mFormats.add(config->format);
+
+    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
+    devDesc->mAddress = address;
+    profile->mSupportedDevices.add(devDesc);
+
+    mOutputProfiles.add(profile);
+
+    return NO_ERROR;
+}
+
+status_t HwModule::removeOutputProfile(String8 name)
+{
+    for (size_t i = 0; i < mOutputProfiles.size(); i++) {
+        if (mOutputProfiles[i]->mName == name) {
+            mOutputProfiles.removeAt(i);
+            break;
+        }
+    }
+
+    return NO_ERROR;
+}
+
+status_t HwModule::addInputProfile(String8 name, const audio_config_t *config,
+                                                  audio_devices_t device, String8 address)
+{
+    sp<IOProfile> profile = new IOProfile(name, AUDIO_PORT_ROLE_SINK, this);
+
+    profile->mSamplingRates.add(config->sample_rate);
+    profile->mChannelMasks.add(config->channel_mask);
+    profile->mFormats.add(config->format);
+
+    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
+    devDesc->mAddress = address;
+    profile->mSupportedDevices.add(devDesc);
+
+    ALOGV("addInputProfile() name %s rate %d mask 0x08", name.string(), config->sample_rate, config->channel_mask);
+
+    mInputProfiles.add(profile);
+
+    return NO_ERROR;
+}
+
+status_t HwModule::removeInputProfile(String8 name)
+{
+    for (size_t i = 0; i < mInputProfiles.size(); i++) {
+        if (mInputProfiles[i]->mName == name) {
+            mInputProfiles.removeAt(i);
+            break;
+        }
+    }
+
+    return NO_ERROR;
+}
+
+
+void HwModule::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "  - name: %s\n", mName);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "  - handle: %d\n", mHandle);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "  - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    if (mOutputProfiles.size()) {
+        write(fd, "  - outputs:\n", strlen("  - outputs:\n"));
+        for (size_t i = 0; i < mOutputProfiles.size(); i++) {
+            snprintf(buffer, SIZE, "    output %zu:\n", i);
+            write(fd, buffer, strlen(buffer));
+            mOutputProfiles[i]->dump(fd);
+        }
+    }
+    if (mInputProfiles.size()) {
+        write(fd, "  - inputs:\n", strlen("  - inputs:\n"));
+        for (size_t i = 0; i < mInputProfiles.size(); i++) {
+            snprintf(buffer, SIZE, "    input %zu:\n", i);
+            write(fd, buffer, strlen(buffer));
+            mInputProfiles[i]->dump(fd);
+        }
+    }
+    if (mDeclaredDevices.size()) {
+        write(fd, "  - devices:\n", strlen("  - devices:\n"));
+        for (size_t i = 0; i < mDeclaredDevices.size(); i++) {
+            mDeclaredDevices[i]->dump(fd, 4, i);
+        }
+    }
+}
+
+} //namespace android
diff --git a/services/audiopolicy/managerdefault/HwModule.h b/services/audiopolicy/managerdefault/HwModule.h
new file mode 100644
index 0000000..f814dd9
--- /dev/null
+++ b/services/audiopolicy/managerdefault/HwModule.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+namespace android {
+
+class HwModule : public RefBase
+{
+public:
+    HwModule(const char *name);
+    ~HwModule();
+
+    status_t loadOutput(cnode *root);
+    status_t loadInput(cnode *root);
+    status_t loadDevice(cnode *root);
+
+    status_t addOutputProfile(String8 name, const audio_config_t *config,
+            audio_devices_t device, String8 address);
+    status_t removeOutputProfile(String8 name);
+    status_t addInputProfile(String8 name, const audio_config_t *config,
+            audio_devices_t device, String8 address);
+    status_t removeInputProfile(String8 name);
+
+    void dump(int fd);
+
+    const char *const        mName; // base name of the audio HW module (primary, a2dp ...)
+    uint32_t                 mHalVersion; // audio HAL API version
+    audio_module_handle_t    mHandle;
+    Vector < sp<IOProfile> > mOutputProfiles; // output profiles exposed by this module
+    Vector < sp<IOProfile> > mInputProfiles;  // input profiles exposed by this module
+    DeviceVector             mDeclaredDevices; // devices declared in audio_policy.conf
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/IOProfile.cpp b/services/audiopolicy/managerdefault/IOProfile.cpp
new file mode 100644
index 0000000..538ac1a
--- /dev/null
+++ b/services/audiopolicy/managerdefault/IOProfile.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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 "APM::IOProfile"
+//#define LOG_NDEBUG 0
+
+#include "AudioPolicyManager.h"
+
+namespace android {
+
+IOProfile::IOProfile(const String8& name, audio_port_role_t role,
+                                         const sp<HwModule>& module)
+    : AudioPort(name, AUDIO_PORT_TYPE_MIX, role, module)
+{
+}
+
+IOProfile::~IOProfile()
+{
+}
+
+// checks if the IO profile is compatible with specified parameters.
+// Sampling rate, format and channel mask must be specified in order to
+// get a valid a match
+bool IOProfile::isCompatibleProfile(audio_devices_t device,
+                                                        String8 address,
+                                                        uint32_t samplingRate,
+                                                        uint32_t *updatedSamplingRate,
+                                                        audio_format_t format,
+                                                        audio_channel_mask_t channelMask,
+                                                        uint32_t flags) const
+{
+    const bool isPlaybackThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SOURCE;
+    const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
+    ALOG_ASSERT(isPlaybackThread != isRecordThread);
+
+    if (device != AUDIO_DEVICE_NONE && mSupportedDevices.getDevice(device, address) == 0) {
+        return false;
+    }
+
+    if (samplingRate == 0) {
+         return false;
+    }
+    uint32_t myUpdatedSamplingRate = samplingRate;
+    if (isPlaybackThread && checkExactSamplingRate(samplingRate) != NO_ERROR) {
+         return false;
+    }
+    if (isRecordThread && checkCompatibleSamplingRate(samplingRate, &myUpdatedSamplingRate) !=
+            NO_ERROR) {
+         return false;
+    }
+
+    if (!audio_is_valid_format(format) || checkFormat(format) != NO_ERROR) {
+        return false;
+    }
+
+    if (isPlaybackThread && (!audio_is_output_channel(channelMask) ||
+            checkExactChannelMask(channelMask) != NO_ERROR)) {
+        return false;
+    }
+    if (isRecordThread && (!audio_is_input_channel(channelMask) ||
+            checkCompatibleChannelMask(channelMask) != NO_ERROR)) {
+        return false;
+    }
+
+    if (isPlaybackThread && (mFlags & flags) != flags) {
+        return false;
+    }
+    // The only input flag that is allowed to be different is the fast flag.
+    // An existing fast stream is compatible with a normal track request.
+    // An existing normal stream is compatible with a fast track request,
+    // but the fast request will be denied by AudioFlinger and converted to normal track.
+    if (isRecordThread && ((mFlags ^ flags) &
+            ~AUDIO_INPUT_FLAG_FAST)) {
+        return false;
+    }
+
+    if (updatedSamplingRate != NULL) {
+        *updatedSamplingRate = myUpdatedSamplingRate;
+    }
+    return true;
+}
+
+void IOProfile::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    AudioPort::dump(fd, 4);
+
+    snprintf(buffer, SIZE, "    - flags: 0x%04x\n", mFlags);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "    - devices:\n");
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    for (size_t i = 0; i < mSupportedDevices.size(); i++) {
+        mSupportedDevices[i]->dump(fd, 6, i);
+    }
+}
+
+void IOProfile::log()
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    ALOGV("    - sampling rates: ");
+    for (size_t i = 0; i < mSamplingRates.size(); i++) {
+        ALOGV("  %d", mSamplingRates[i]);
+    }
+
+    ALOGV("    - channel masks: ");
+    for (size_t i = 0; i < mChannelMasks.size(); i++) {
+        ALOGV("  0x%04x", mChannelMasks[i]);
+    }
+
+    ALOGV("    - formats: ");
+    for (size_t i = 0; i < mFormats.size(); i++) {
+        ALOGV("  0x%08x", mFormats[i]);
+    }
+
+    ALOGV("    - devices: 0x%04x\n", mSupportedDevices.types());
+    ALOGV("    - flags: 0x%04x\n", mFlags);
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/IOProfile.h b/services/audiopolicy/managerdefault/IOProfile.h
new file mode 100644
index 0000000..3317969
--- /dev/null
+++ b/services/audiopolicy/managerdefault/IOProfile.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+namespace android {
+
+class HwModule;
+
+// the IOProfile class describes the capabilities of an output or input stream.
+// It is currently assumed that all combination of listed parameters are supported.
+// It is used by the policy manager to determine if an output or input is suitable for
+// a given use case,  open/close it accordingly and connect/disconnect audio tracks
+// to/from it.
+class IOProfile : public AudioPort
+{
+public:
+    IOProfile(const String8& name, audio_port_role_t role, const sp<HwModule>& module);
+    virtual ~IOProfile();
+
+    // This method is used for both output and input.
+    // If parameter updatedSamplingRate is non-NULL, it is assigned the actual sample rate.
+    // For input, flags is interpreted as audio_input_flags_t.
+    // TODO: merge audio_output_flags_t and audio_input_flags_t.
+    bool isCompatibleProfile(audio_devices_t device,
+                             String8 address,
+                             uint32_t samplingRate,
+                             uint32_t *updatedSamplingRate,
+                             audio_format_t format,
+                             audio_channel_mask_t channelMask,
+                             uint32_t flags) const;
+
+    void dump(int fd);
+    void log();
+
+    DeviceVector  mSupportedDevices; // supported devices
+                                     // (devices this output can be routed to)
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Ports.cpp b/services/audiopolicy/managerdefault/Ports.cpp
new file mode 100644
index 0000000..3e55cee
--- /dev/null
+++ b/services/audiopolicy/managerdefault/Ports.cpp
@@ -0,0 +1,844 @@
+/*
+ * 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 "APM::Ports"
+//#define LOG_NDEBUG 0
+
+#include "AudioPolicyManager.h"
+
+#include "audio_policy_conf.h"
+
+namespace android {
+
+// --- AudioPort class implementation
+
+AudioPort::AudioPort(const String8& name, audio_port_type_t type,
+          audio_port_role_t role, const sp<HwModule>& module) :
+    mName(name), mType(type), mRole(role), mModule(module), mFlags(0), mId(0)
+{
+    mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
+                    ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
+}
+
+void AudioPort::attach(const sp<HwModule>& module) {
+    mId = AudioPolicyManager::nextUniqueId();
+    mModule = module;
+}
+
+void AudioPort::toAudioPort(struct audio_port *port) const
+{
+    port->role = mRole;
+    port->type = mType;
+    strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
+    unsigned int i;
+    for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) {
+        if (mSamplingRates[i] != 0) {
+            port->sample_rates[i] = mSamplingRates[i];
+        }
+    }
+    port->num_sample_rates = i;
+    for (i = 0; i < mChannelMasks.size() && i < AUDIO_PORT_MAX_CHANNEL_MASKS; i++) {
+        if (mChannelMasks[i] != 0) {
+            port->channel_masks[i] = mChannelMasks[i];
+        }
+    }
+    port->num_channel_masks = i;
+    for (i = 0; i < mFormats.size() && i < AUDIO_PORT_MAX_FORMATS; i++) {
+        if (mFormats[i] != 0) {
+            port->formats[i] = mFormats[i];
+        }
+    }
+    port->num_formats = i;
+
+    ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
+
+    for (i = 0; i < mGains.size() && i < AUDIO_PORT_MAX_GAINS; i++) {
+        port->gains[i] = mGains[i]->mGain;
+    }
+    port->num_gains = i;
+}
+
+void AudioPort::importAudioPort(const sp<AudioPort> port) {
+    for (size_t k = 0 ; k < port->mSamplingRates.size() ; k++) {
+        const uint32_t rate = port->mSamplingRates.itemAt(k);
+        if (rate != 0) { // skip "dynamic" rates
+            bool hasRate = false;
+            for (size_t l = 0 ; l < mSamplingRates.size() ; l++) {
+                if (rate == mSamplingRates.itemAt(l)) {
+                    hasRate = true;
+                    break;
+                }
+            }
+            if (!hasRate) { // never import a sampling rate twice
+                mSamplingRates.add(rate);
+            }
+        }
+    }
+    for (size_t k = 0 ; k < port->mChannelMasks.size() ; k++) {
+        const audio_channel_mask_t mask = port->mChannelMasks.itemAt(k);
+        if (mask != 0) { // skip "dynamic" masks
+            bool hasMask = false;
+            for (size_t l = 0 ; l < mChannelMasks.size() ; l++) {
+                if (mask == mChannelMasks.itemAt(l)) {
+                    hasMask = true;
+                    break;
+                }
+            }
+            if (!hasMask) { // never import a channel mask twice
+                mChannelMasks.add(mask);
+            }
+        }
+    }
+    for (size_t k = 0 ; k < port->mFormats.size() ; k++) {
+        const audio_format_t format = port->mFormats.itemAt(k);
+        if (format != 0) { // skip "dynamic" formats
+            bool hasFormat = false;
+            for (size_t l = 0 ; l < mFormats.size() ; l++) {
+                if (format == mFormats.itemAt(l)) {
+                    hasFormat = true;
+                    break;
+                }
+            }
+            if (!hasFormat) { // never import a channel mask twice
+                mFormats.add(format);
+            }
+        }
+    }
+    for (size_t k = 0 ; k < port->mGains.size() ; k++) {
+        sp<AudioGain> gain = port->mGains.itemAt(k);
+        if (gain != 0) {
+            bool hasGain = false;
+            for (size_t l = 0 ; l < mGains.size() ; l++) {
+                if (gain == mGains.itemAt(l)) {
+                    hasGain = true;
+                    break;
+                }
+            }
+            if (!hasGain) { // never import a gain twice
+                mGains.add(gain);
+            }
+        }
+    }
+}
+
+void AudioPort::clearCapabilities() {
+    mChannelMasks.clear();
+    mFormats.clear();
+    mSamplingRates.clear();
+    mGains.clear();
+}
+
+void AudioPort::loadSamplingRates(char *name)
+{
+    char *str = strtok(name, "|");
+
+    // by convention, "0' in the first entry in mSamplingRates indicates the supported sampling
+    // rates should be read from the output stream after it is opened for the first time
+    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
+        mSamplingRates.add(0);
+        return;
+    }
+
+    while (str != NULL) {
+        uint32_t rate = atoi(str);
+        if (rate != 0) {
+            ALOGV("loadSamplingRates() adding rate %d", rate);
+            mSamplingRates.add(rate);
+        }
+        str = strtok(NULL, "|");
+    }
+}
+
+void AudioPort::loadFormats(char *name)
+{
+    char *str = strtok(name, "|");
+
+    // by convention, "0' in the first entry in mFormats indicates the supported formats
+    // should be read from the output stream after it is opened for the first time
+    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
+        mFormats.add(AUDIO_FORMAT_DEFAULT);
+        return;
+    }
+
+    while (str != NULL) {
+        audio_format_t format = (audio_format_t)ConfigParsingUtils::stringToEnum(sFormatNameToEnumTable,
+                                                             ARRAY_SIZE(sFormatNameToEnumTable),
+                                                             str);
+        if (format != AUDIO_FORMAT_DEFAULT) {
+            mFormats.add(format);
+        }
+        str = strtok(NULL, "|");
+    }
+}
+
+void AudioPort::loadInChannels(char *name)
+{
+    const char *str = strtok(name, "|");
+
+    ALOGV("loadInChannels() %s", name);
+
+    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
+        mChannelMasks.add(0);
+        return;
+    }
+
+    while (str != NULL) {
+        audio_channel_mask_t channelMask =
+                (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
+                                                   ARRAY_SIZE(sInChannelsNameToEnumTable),
+                                                   str);
+        if (channelMask != 0) {
+            ALOGV("loadInChannels() adding channelMask %04x", channelMask);
+            mChannelMasks.add(channelMask);
+        }
+        str = strtok(NULL, "|");
+    }
+}
+
+void AudioPort::loadOutChannels(char *name)
+{
+    const char *str = strtok(name, "|");
+
+    ALOGV("loadOutChannels() %s", name);
+
+    // by convention, "0' in the first entry in mChannelMasks indicates the supported channel
+    // masks should be read from the output stream after it is opened for the first time
+    if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0) {
+        mChannelMasks.add(0);
+        return;
+    }
+
+    while (str != NULL) {
+        audio_channel_mask_t channelMask =
+                (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
+                                                   ARRAY_SIZE(sOutChannelsNameToEnumTable),
+                                                   str);
+        if (channelMask != 0) {
+            mChannelMasks.add(channelMask);
+        }
+        str = strtok(NULL, "|");
+    }
+    return;
+}
+
+audio_gain_mode_t AudioPort::loadGainMode(char *name)
+{
+    const char *str = strtok(name, "|");
+
+    ALOGV("loadGainMode() %s", name);
+    audio_gain_mode_t mode = 0;
+    while (str != NULL) {
+        mode |= (audio_gain_mode_t)ConfigParsingUtils::stringToEnum(sGainModeNameToEnumTable,
+                                                ARRAY_SIZE(sGainModeNameToEnumTable),
+                                                str);
+        str = strtok(NULL, "|");
+    }
+    return mode;
+}
+
+void AudioPort::loadGain(cnode *root, int index)
+{
+    cnode *node = root->first_child;
+
+    sp<AudioGain> gain = new AudioGain(index, mUseInChannelMask);
+
+    while (node) {
+        if (strcmp(node->name, GAIN_MODE) == 0) {
+            gain->mGain.mode = loadGainMode((char *)node->value);
+        } else if (strcmp(node->name, GAIN_CHANNELS) == 0) {
+            if (mUseInChannelMask) {
+                gain->mGain.channel_mask =
+                        (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sInChannelsNameToEnumTable,
+                                                           ARRAY_SIZE(sInChannelsNameToEnumTable),
+                                                           (char *)node->value);
+            } else {
+                gain->mGain.channel_mask =
+                        (audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
+                                                           ARRAY_SIZE(sOutChannelsNameToEnumTable),
+                                                           (char *)node->value);
+            }
+        } else if (strcmp(node->name, GAIN_MIN_VALUE) == 0) {
+            gain->mGain.min_value = atoi((char *)node->value);
+        } else if (strcmp(node->name, GAIN_MAX_VALUE) == 0) {
+            gain->mGain.max_value = atoi((char *)node->value);
+        } else if (strcmp(node->name, GAIN_DEFAULT_VALUE) == 0) {
+            gain->mGain.default_value = atoi((char *)node->value);
+        } else if (strcmp(node->name, GAIN_STEP_VALUE) == 0) {
+            gain->mGain.step_value = atoi((char *)node->value);
+        } else if (strcmp(node->name, GAIN_MIN_RAMP_MS) == 0) {
+            gain->mGain.min_ramp_ms = atoi((char *)node->value);
+        } else if (strcmp(node->name, GAIN_MAX_RAMP_MS) == 0) {
+            gain->mGain.max_ramp_ms = atoi((char *)node->value);
+        }
+        node = node->next;
+    }
+
+    ALOGV("loadGain() adding new gain mode %08x channel mask %08x min mB %d max mB %d",
+          gain->mGain.mode, gain->mGain.channel_mask, gain->mGain.min_value, gain->mGain.max_value);
+
+    if (gain->mGain.mode == 0) {
+        return;
+    }
+    mGains.add(gain);
+}
+
+void AudioPort::loadGains(cnode *root)
+{
+    cnode *node = root->first_child;
+    int index = 0;
+    while (node) {
+        ALOGV("loadGains() loading gain %s", node->name);
+        loadGain(node, index++);
+        node = node->next;
+    }
+}
+
+status_t AudioPort::checkExactSamplingRate(uint32_t samplingRate) const
+{
+    if (mSamplingRates.isEmpty()) {
+        return NO_ERROR;
+    }
+
+    for (size_t i = 0; i < mSamplingRates.size(); i ++) {
+        if (mSamplingRates[i] == samplingRate) {
+            return NO_ERROR;
+        }
+    }
+    return BAD_VALUE;
+}
+
+status_t AudioPort::checkCompatibleSamplingRate(uint32_t samplingRate,
+        uint32_t *updatedSamplingRate) const
+{
+    if (mSamplingRates.isEmpty()) {
+        return NO_ERROR;
+    }
+
+    // Search for the closest supported sampling rate that is above (preferred)
+    // or below (acceptable) the desired sampling rate, within a permitted ratio.
+    // The sampling rates do not need to be sorted in ascending order.
+    ssize_t maxBelow = -1;
+    ssize_t minAbove = -1;
+    uint32_t candidate;
+    for (size_t i = 0; i < mSamplingRates.size(); i++) {
+        candidate = mSamplingRates[i];
+        if (candidate == samplingRate) {
+            if (updatedSamplingRate != NULL) {
+                *updatedSamplingRate = candidate;
+            }
+            return NO_ERROR;
+        }
+        // candidate < desired
+        if (candidate < samplingRate) {
+            if (maxBelow < 0 || candidate > mSamplingRates[maxBelow]) {
+                maxBelow = i;
+            }
+        // candidate > desired
+        } else {
+            if (minAbove < 0 || candidate < mSamplingRates[minAbove]) {
+                minAbove = i;
+            }
+        }
+    }
+    // This uses hard-coded knowledge about AudioFlinger resampling ratios.
+    // TODO Move these assumptions out.
+    static const uint32_t kMaxDownSampleRatio = 6;  // beyond this aliasing occurs
+    static const uint32_t kMaxUpSampleRatio = 256;  // beyond this sample rate inaccuracies occur
+                                                    // due to approximation by an int32_t of the
+                                                    // phase increments
+    // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
+    if (minAbove >= 0) {
+        candidate = mSamplingRates[minAbove];
+        if (candidate / kMaxDownSampleRatio <= samplingRate) {
+            if (updatedSamplingRate != NULL) {
+                *updatedSamplingRate = candidate;
+            }
+            return NO_ERROR;
+        }
+    }
+    // But if we have to up-sample from a lower sampling rate, that's OK.
+    if (maxBelow >= 0) {
+        candidate = mSamplingRates[maxBelow];
+        if (candidate * kMaxUpSampleRatio >= samplingRate) {
+            if (updatedSamplingRate != NULL) {
+                *updatedSamplingRate = candidate;
+            }
+            return NO_ERROR;
+        }
+    }
+    // leave updatedSamplingRate unmodified
+    return BAD_VALUE;
+}
+
+status_t AudioPort::checkExactChannelMask(audio_channel_mask_t channelMask) const
+{
+    if (mChannelMasks.isEmpty()) {
+        return NO_ERROR;
+    }
+
+    for (size_t i = 0; i < mChannelMasks.size(); i++) {
+        if (mChannelMasks[i] == channelMask) {
+            return NO_ERROR;
+        }
+    }
+    return BAD_VALUE;
+}
+
+status_t AudioPort::checkCompatibleChannelMask(audio_channel_mask_t channelMask)
+        const
+{
+    if (mChannelMasks.isEmpty()) {
+        return NO_ERROR;
+    }
+
+    const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
+    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
+        // FIXME Does not handle multi-channel automatic conversions yet
+        audio_channel_mask_t supported = mChannelMasks[i];
+        if (supported == channelMask) {
+            return NO_ERROR;
+        }
+        if (isRecordThread) {
+            // This uses hard-coded knowledge that AudioFlinger can silently down-mix and up-mix.
+            // FIXME Abstract this out to a table.
+            if (((supported == AUDIO_CHANNEL_IN_FRONT_BACK || supported == AUDIO_CHANNEL_IN_STEREO)
+                    && channelMask == AUDIO_CHANNEL_IN_MONO) ||
+                (supported == AUDIO_CHANNEL_IN_MONO && (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK
+                    || channelMask == AUDIO_CHANNEL_IN_STEREO))) {
+                return NO_ERROR;
+            }
+        }
+    }
+    return BAD_VALUE;
+}
+
+status_t AudioPort::checkFormat(audio_format_t format) const
+{
+    if (mFormats.isEmpty()) {
+        return NO_ERROR;
+    }
+
+    for (size_t i = 0; i < mFormats.size(); i ++) {
+        if (mFormats[i] == format) {
+            return NO_ERROR;
+        }
+    }
+    return BAD_VALUE;
+}
+
+
+uint32_t AudioPort::pickSamplingRate() const
+{
+    // special case for uninitialized dynamic profile
+    if (mSamplingRates.size() == 1 && mSamplingRates[0] == 0) {
+        return 0;
+    }
+
+    // For direct outputs, pick minimum sampling rate: this helps ensuring that the
+    // channel count / sampling rate combination chosen will be supported by the connected
+    // sink
+    if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
+            (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) {
+        uint32_t samplingRate = UINT_MAX;
+        for (size_t i = 0; i < mSamplingRates.size(); i ++) {
+            if ((mSamplingRates[i] < samplingRate) && (mSamplingRates[i] > 0)) {
+                samplingRate = mSamplingRates[i];
+            }
+        }
+        return (samplingRate == UINT_MAX) ? 0 : samplingRate;
+    }
+
+    uint32_t samplingRate = 0;
+    uint32_t maxRate = MAX_MIXER_SAMPLING_RATE;
+
+    // For mixed output and inputs, use max mixer sampling rates. Do not
+    // limit sampling rate otherwise
+    if (mType != AUDIO_PORT_TYPE_MIX) {
+        maxRate = UINT_MAX;
+    }
+    for (size_t i = 0; i < mSamplingRates.size(); i ++) {
+        if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) {
+            samplingRate = mSamplingRates[i];
+        }
+    }
+    return samplingRate;
+}
+
+audio_channel_mask_t AudioPort::pickChannelMask() const
+{
+    // special case for uninitialized dynamic profile
+    if (mChannelMasks.size() == 1 && mChannelMasks[0] == 0) {
+        return AUDIO_CHANNEL_NONE;
+    }
+    audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE;
+
+    // For direct outputs, pick minimum channel count: this helps ensuring that the
+    // channel count / sampling rate combination chosen will be supported by the connected
+    // sink
+    if ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
+            (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))) {
+        uint32_t channelCount = UINT_MAX;
+        for (size_t i = 0; i < mChannelMasks.size(); i ++) {
+            uint32_t cnlCount;
+            if (mUseInChannelMask) {
+                cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
+            } else {
+                cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
+            }
+            if ((cnlCount < channelCount) && (cnlCount > 0)) {
+                channelMask = mChannelMasks[i];
+                channelCount = cnlCount;
+            }
+        }
+        return channelMask;
+    }
+
+    uint32_t channelCount = 0;
+    uint32_t maxCount = MAX_MIXER_CHANNEL_COUNT;
+
+    // For mixed output and inputs, use max mixer channel count. Do not
+    // limit channel count otherwise
+    if (mType != AUDIO_PORT_TYPE_MIX) {
+        maxCount = UINT_MAX;
+    }
+    for (size_t i = 0; i < mChannelMasks.size(); i ++) {
+        uint32_t cnlCount;
+        if (mUseInChannelMask) {
+            cnlCount = audio_channel_count_from_in_mask(mChannelMasks[i]);
+        } else {
+            cnlCount = audio_channel_count_from_out_mask(mChannelMasks[i]);
+        }
+        if ((cnlCount > channelCount) && (cnlCount <= maxCount)) {
+            channelMask = mChannelMasks[i];
+            channelCount = cnlCount;
+        }
+    }
+    return channelMask;
+}
+
+/* format in order of increasing preference */
+const audio_format_t AudioPort::sPcmFormatCompareTable[] = {
+        AUDIO_FORMAT_DEFAULT,
+        AUDIO_FORMAT_PCM_16_BIT,
+        AUDIO_FORMAT_PCM_8_24_BIT,
+        AUDIO_FORMAT_PCM_24_BIT_PACKED,
+        AUDIO_FORMAT_PCM_32_BIT,
+        AUDIO_FORMAT_PCM_FLOAT,
+};
+
+int AudioPort::compareFormats(audio_format_t format1,
+                                                  audio_format_t format2)
+{
+    // NOTE: AUDIO_FORMAT_INVALID is also considered not PCM and will be compared equal to any
+    // compressed format and better than any PCM format. This is by design of pickFormat()
+    if (!audio_is_linear_pcm(format1)) {
+        if (!audio_is_linear_pcm(format2)) {
+            return 0;
+        }
+        return 1;
+    }
+    if (!audio_is_linear_pcm(format2)) {
+        return -1;
+    }
+
+    int index1 = -1, index2 = -1;
+    for (size_t i = 0;
+            (i < ARRAY_SIZE(sPcmFormatCompareTable)) && ((index1 == -1) || (index2 == -1));
+            i ++) {
+        if (sPcmFormatCompareTable[i] == format1) {
+            index1 = i;
+        }
+        if (sPcmFormatCompareTable[i] == format2) {
+            index2 = i;
+        }
+    }
+    // format1 not found => index1 < 0 => format2 > format1
+    // format2 not found => index2 < 0 => format2 < format1
+    return index1 - index2;
+}
+
+audio_format_t AudioPort::pickFormat() const
+{
+    // special case for uninitialized dynamic profile
+    if (mFormats.size() == 1 && mFormats[0] == 0) {
+        return AUDIO_FORMAT_DEFAULT;
+    }
+
+    audio_format_t format = AUDIO_FORMAT_DEFAULT;
+    audio_format_t bestFormat =
+            AudioPort::sPcmFormatCompareTable[
+                ARRAY_SIZE(AudioPort::sPcmFormatCompareTable) - 1];
+    // For mixed output and inputs, use best mixer output format. Do not
+    // limit format otherwise
+    if ((mType != AUDIO_PORT_TYPE_MIX) ||
+            ((mRole == AUDIO_PORT_ROLE_SOURCE) &&
+             (((mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) != 0)))) {
+        bestFormat = AUDIO_FORMAT_INVALID;
+    }
+
+    for (size_t i = 0; i < mFormats.size(); i ++) {
+        if ((compareFormats(mFormats[i], format) > 0) &&
+                (compareFormats(mFormats[i], bestFormat) <= 0)) {
+            format = mFormats[i];
+        }
+    }
+    return format;
+}
+
+status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig,
+                                                  int index) const
+{
+    if (index < 0 || (size_t)index >= mGains.size()) {
+        return BAD_VALUE;
+    }
+    return mGains[index]->checkConfig(gainConfig);
+}
+
+void AudioPort::dump(int fd, int spaces) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    if (mName.size() != 0) {
+        snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string());
+        result.append(buffer);
+    }
+
+    if (mSamplingRates.size() != 0) {
+        snprintf(buffer, SIZE, "%*s- sampling rates: ", spaces, "");
+        result.append(buffer);
+        for (size_t i = 0; i < mSamplingRates.size(); i++) {
+            if (i == 0 && mSamplingRates[i] == 0) {
+                snprintf(buffer, SIZE, "Dynamic");
+            } else {
+                snprintf(buffer, SIZE, "%d", mSamplingRates[i]);
+            }
+            result.append(buffer);
+            result.append(i == (mSamplingRates.size() - 1) ? "" : ", ");
+        }
+        result.append("\n");
+    }
+
+    if (mChannelMasks.size() != 0) {
+        snprintf(buffer, SIZE, "%*s- channel masks: ", spaces, "");
+        result.append(buffer);
+        for (size_t i = 0; i < mChannelMasks.size(); i++) {
+            ALOGV("AudioPort::dump mChannelMasks %zu %08x", i, mChannelMasks[i]);
+
+            if (i == 0 && mChannelMasks[i] == 0) {
+                snprintf(buffer, SIZE, "Dynamic");
+            } else {
+                snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]);
+            }
+            result.append(buffer);
+            result.append(i == (mChannelMasks.size() - 1) ? "" : ", ");
+        }
+        result.append("\n");
+    }
+
+    if (mFormats.size() != 0) {
+        snprintf(buffer, SIZE, "%*s- formats: ", spaces, "");
+        result.append(buffer);
+        for (size_t i = 0; i < mFormats.size(); i++) {
+            const char *formatStr = ConfigParsingUtils::enumToString(sFormatNameToEnumTable,
+                                                 ARRAY_SIZE(sFormatNameToEnumTable),
+                                                 mFormats[i]);
+            if (i == 0 && strcmp(formatStr, "") == 0) {
+                snprintf(buffer, SIZE, "Dynamic");
+            } else {
+                snprintf(buffer, SIZE, "%s", formatStr);
+            }
+            result.append(buffer);
+            result.append(i == (mFormats.size() - 1) ? "" : ", ");
+        }
+        result.append("\n");
+    }
+    write(fd, result.string(), result.size());
+    if (mGains.size() != 0) {
+        snprintf(buffer, SIZE, "%*s- gains:\n", spaces, "");
+        write(fd, buffer, strlen(buffer) + 1);
+        result.append(buffer);
+        for (size_t i = 0; i < mGains.size(); i++) {
+            mGains[i]->dump(fd, spaces + 2, i);
+        }
+    }
+}
+
+
+// --- AudioPortConfig class implementation
+
+AudioPortConfig::AudioPortConfig()
+{
+    mSamplingRate = 0;
+    mChannelMask = AUDIO_CHANNEL_NONE;
+    mFormat = AUDIO_FORMAT_INVALID;
+    mGain.index = -1;
+}
+
+status_t AudioPortConfig::applyAudioPortConfig(
+                                                        const struct audio_port_config *config,
+                                                        struct audio_port_config *backupConfig)
+{
+    struct audio_port_config localBackupConfig;
+    status_t status = NO_ERROR;
+
+    localBackupConfig.config_mask = config->config_mask;
+    toAudioPortConfig(&localBackupConfig);
+
+    sp<AudioPort> audioport = getAudioPort();
+    if (audioport == 0) {
+        status = NO_INIT;
+        goto exit;
+    }
+    if (config->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
+        status = audioport->checkExactSamplingRate(config->sample_rate);
+        if (status != NO_ERROR) {
+            goto exit;
+        }
+        mSamplingRate = config->sample_rate;
+    }
+    if (config->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
+        status = audioport->checkExactChannelMask(config->channel_mask);
+        if (status != NO_ERROR) {
+            goto exit;
+        }
+        mChannelMask = config->channel_mask;
+    }
+    if (config->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
+        status = audioport->checkFormat(config->format);
+        if (status != NO_ERROR) {
+            goto exit;
+        }
+        mFormat = config->format;
+    }
+    if (config->config_mask & AUDIO_PORT_CONFIG_GAIN) {
+        status = audioport->checkGain(&config->gain, config->gain.index);
+        if (status != NO_ERROR) {
+            goto exit;
+        }
+        mGain = config->gain;
+    }
+
+exit:
+    if (status != NO_ERROR) {
+        applyAudioPortConfig(&localBackupConfig);
+    }
+    if (backupConfig != NULL) {
+        *backupConfig = localBackupConfig;
+    }
+    return status;
+}
+
+void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
+                                        const struct audio_port_config *srcConfig) const
+{
+    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
+        dstConfig->sample_rate = mSamplingRate;
+        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)) {
+            dstConfig->sample_rate = srcConfig->sample_rate;
+        }
+    } else {
+        dstConfig->sample_rate = 0;
+    }
+    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
+        dstConfig->channel_mask = mChannelMask;
+        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)) {
+            dstConfig->channel_mask = srcConfig->channel_mask;
+        }
+    } else {
+        dstConfig->channel_mask = AUDIO_CHANNEL_NONE;
+    }
+    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT) {
+        dstConfig->format = mFormat;
+        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)) {
+            dstConfig->format = srcConfig->format;
+        }
+    } else {
+        dstConfig->format = AUDIO_FORMAT_INVALID;
+    }
+    if (dstConfig->config_mask & AUDIO_PORT_CONFIG_GAIN) {
+        dstConfig->gain = mGain;
+        if ((srcConfig != NULL) && (srcConfig->config_mask & AUDIO_PORT_CONFIG_GAIN)) {
+            dstConfig->gain = srcConfig->gain;
+        }
+    } else {
+        dstConfig->gain.index = -1;
+    }
+    if (dstConfig->gain.index != -1) {
+        dstConfig->config_mask |= AUDIO_PORT_CONFIG_GAIN;
+    } else {
+        dstConfig->config_mask &= ~AUDIO_PORT_CONFIG_GAIN;
+    }
+}
+
+
+// --- AudioPatch class implementation
+
+AudioPatch::AudioPatch(audio_patch_handle_t handle,
+            const struct audio_patch *patch, uid_t uid) :
+                mHandle(handle), mPatch(*patch), mUid(uid), mAfPatchHandle(0)
+{}
+
+status_t AudioPatch::dump(int fd, int spaces, int index) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "%*sAudio patch %d:\n", spaces, "", index+1);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- handle: %2d\n", spaces, "", mHandle);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- audio flinger handle: %2d\n", spaces, "", mAfPatchHandle);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "%*s- %d sources:\n", spaces, "", mPatch.num_sources);
+    result.append(buffer);
+    for (size_t i = 0; i < mPatch.num_sources; i++) {
+        if (mPatch.sources[i].type == AUDIO_PORT_TYPE_DEVICE) {
+            snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
+                     mPatch.sources[i].id, ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
+                                                        ARRAY_SIZE(sDeviceNameToEnumTable),
+                                                        mPatch.sources[i].ext.device.type));
+        } else {
+            snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "",
+                     mPatch.sources[i].id, mPatch.sources[i].ext.mix.handle);
+        }
+        result.append(buffer);
+    }
+    snprintf(buffer, SIZE, "%*s- %d sinks:\n", spaces, "", mPatch.num_sinks);
+    result.append(buffer);
+    for (size_t i = 0; i < mPatch.num_sinks; i++) {
+        if (mPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE) {
+            snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
+                     mPatch.sinks[i].id, ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
+                                                        ARRAY_SIZE(sDeviceNameToEnumTable),
+                                                        mPatch.sinks[i].ext.device.type));
+        } else {
+            snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "",
+                     mPatch.sinks[i].id, mPatch.sinks[i].ext.mix.handle);
+        }
+        result.append(buffer);
+    }
+
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Ports.h b/services/audiopolicy/managerdefault/Ports.h
new file mode 100644
index 0000000..f6e0e93
--- /dev/null
+++ b/services/audiopolicy/managerdefault/Ports.h
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+namespace android {
+
+class HwModule;
+
+class AudioPort: public virtual RefBase
+{
+public:
+    AudioPort(const String8& name, audio_port_type_t type,
+            audio_port_role_t role, const sp<HwModule>& module);
+    virtual ~AudioPort() {}
+
+    audio_port_handle_t getHandle() { return mId; }
+
+    void attach(const sp<HwModule>& module);
+    bool isAttached() { return mId != 0; }
+
+    virtual void toAudioPort(struct audio_port *port) const;
+
+    void importAudioPort(const sp<AudioPort> port);
+    void clearCapabilities();
+
+    void loadSamplingRates(char *name);
+    void loadFormats(char *name);
+    void loadOutChannels(char *name);
+    void loadInChannels(char *name);
+
+    audio_gain_mode_t loadGainMode(char *name);
+    void loadGain(cnode *root, int index);
+    virtual void loadGains(cnode *root);
+
+    // searches for an exact match
+    status_t checkExactSamplingRate(uint32_t samplingRate) const;
+    // searches for a compatible match, and returns the best match via updatedSamplingRate
+    status_t checkCompatibleSamplingRate(uint32_t samplingRate,
+            uint32_t *updatedSamplingRate) const;
+    // searches for an exact match
+    status_t checkExactChannelMask(audio_channel_mask_t channelMask) const;
+    // searches for a compatible match, currently implemented for input channel masks only
+    status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask) const;
+    status_t checkFormat(audio_format_t format) const;
+    status_t checkGain(const struct audio_gain_config *gainConfig, int index) const;
+
+    uint32_t pickSamplingRate() const;
+    audio_channel_mask_t pickChannelMask() const;
+    audio_format_t pickFormat() const;
+
+    static const audio_format_t sPcmFormatCompareTable[];
+    static int compareFormats(audio_format_t format1, audio_format_t format2);
+
+    void dump(int fd, int spaces) const;
+
+    String8           mName;
+    audio_port_type_t mType;
+    audio_port_role_t mRole;
+    bool              mUseInChannelMask;
+    // by convention, "0' in the first entry in mSamplingRates, mChannelMasks or mFormats
+    // indicates the supported parameters should be read from the output stream
+    // after it is opened for the first time
+    Vector <uint32_t> mSamplingRates; // supported sampling rates
+    Vector <audio_channel_mask_t> mChannelMasks; // supported channel masks
+    Vector <audio_format_t> mFormats; // supported audio formats
+    Vector < sp<AudioGain> > mGains; // gain controllers
+    sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
+    uint32_t mFlags; // attribute flags (e.g primary output,
+                     // direct output...).
+
+
+protected:
+    //TODO - clarify the role of mId in this case, both an "attached" indicator
+    // and a unique ID for identifying a port to the (upcoming) selection API,
+    // and its relationship to the mId in AudioOutputDescriptor and AudioInputDescriptor.
+    audio_port_handle_t mId;
+};
+
+class AudioPortConfig: public virtual RefBase
+{
+public:
+    AudioPortConfig();
+    virtual ~AudioPortConfig() {}
+
+    status_t applyAudioPortConfig(const struct audio_port_config *config,
+            struct audio_port_config *backupConfig = NULL);
+    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
+            const struct audio_port_config *srcConfig = NULL) const = 0;
+    virtual sp<AudioPort> getAudioPort() const = 0;
+    uint32_t mSamplingRate;
+    audio_format_t mFormat;
+    audio_channel_mask_t mChannelMask;
+    struct audio_gain_config mGain;
+};
+
+
+class AudioPatch: public RefBase
+{
+public:
+    AudioPatch(audio_patch_handle_t handle, const struct audio_patch *patch, uid_t uid);
+
+    status_t dump(int fd, int spaces, int index) const;
+
+    audio_patch_handle_t mHandle;
+    struct audio_patch mPatch;
+    uid_t mUid;
+    audio_patch_handle_t mAfPatchHandle;
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/audio_policy_conf.h b/services/audiopolicy/managerdefault/audio_policy_conf.h
similarity index 100%
rename from services/audiopolicy/audio_policy_conf.h
rename to services/audiopolicy/managerdefault/audio_policy_conf.h
diff --git a/services/audiopolicy/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
similarity index 100%
rename from services/audiopolicy/AudioPolicyClientImpl.cpp
rename to services/audiopolicy/service/AudioPolicyClientImpl.cpp
diff --git a/services/audiopolicy/AudioPolicyClientImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp
similarity index 97%
rename from services/audiopolicy/AudioPolicyClientImplLegacy.cpp
rename to services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp
index 97719da..a79f8ae 100644
--- a/services/audiopolicy/AudioPolicyClientImplLegacy.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp
@@ -188,6 +188,13 @@
     if (pSamplingRate == NULL || pFormat == NULL || pChannelMask == NULL || pDevices == NULL) {
         return AUDIO_IO_HANDLE_NONE;
     }
+
+    if (((*pDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) == AUDIO_DEVICE_IN_REMOTE_SUBMIX)
+            && !captureAudioOutputAllowed()) {
+        ALOGE("open_input() permission denied: capture not allowed");
+        return AUDIO_IO_HANDLE_NONE;
+    }
+
     audio_config_t config = AUDIO_CONFIG_INITIALIZER;;
     config.sample_rate = *pSamplingRate;
     config.format = *pFormat;
diff --git a/services/audiopolicy/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
similarity index 97%
rename from services/audiopolicy/AudioPolicyEffects.cpp
rename to services/audiopolicy/service/AudioPolicyEffects.cpp
index e7e1b36..e6ace20 100644
--- a/services/audiopolicy/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -226,6 +226,11 @@
 
     Mutex::Autolock _l(mLock);
     // create audio processors according to stream
+    // FIXME: should we have specific post processing settings for internal streams?
+    // default to media for now.
+    if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
+        stream = AUDIO_STREAM_MUSIC;
+    }
     ssize_t index = mOutputStreams.indexOfKey(stream);
     if (index < 0) {
         ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
@@ -335,7 +340,7 @@
     return (audio_source_t)i;
 }
 
-const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_CNT+1] = {
+const char *AudioPolicyEffects::kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1] = {
     AUDIO_STREAM_DEFAULT_TAG,
     AUDIO_STREAM_VOICE_CALL_TAG,
     AUDIO_STREAM_SYSTEM_TAG,
@@ -350,11 +355,11 @@
 };
 
 // returns the audio_stream_t enum corresponding to the output stream name or
-// AUDIO_STREAM_CNT is no match found
+// AUDIO_STREAM_PUBLIC_CNT is no match found
 audio_stream_type_t AudioPolicyEffects::streamNameToEnum(const char *name)
 {
     int i;
-    for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_CNT; i++) {
+    for (i = AUDIO_STREAM_DEFAULT; i < AUDIO_STREAM_PUBLIC_CNT; i++) {
         if (strcmp(name, kStreamNames[i - AUDIO_STREAM_DEFAULT]) == 0) {
             ALOGV("streamNameToEnum found stream %s %d", name, i);
             break;
@@ -585,7 +590,7 @@
     node = node->first_child;
     while (node) {
         audio_stream_type_t stream = streamNameToEnum(node->name);
-        if (stream == AUDIO_STREAM_CNT) {
+        if (stream == AUDIO_STREAM_PUBLIC_CNT) {
             ALOGW("loadStreamEffectConfigurations() invalid output stream %s", node->name);
             node = node->next;
             continue;
@@ -653,6 +658,10 @@
     loadInputEffectConfigurations(root, effects);
     loadStreamEffectConfigurations(root, effects);
 
+    for (size_t i = 0; i < effects.size(); i++) {
+        delete effects[i];
+    }
+
     config_free(root);
     free(root);
     free(data);
diff --git a/services/audiopolicy/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
similarity index 98%
rename from services/audiopolicy/AudioPolicyEffects.h
rename to services/audiopolicy/service/AudioPolicyEffects.h
index 6b0d538..3dec437 100644
--- a/services/audiopolicy/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -151,7 +151,7 @@
     static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1];
     static audio_source_t inputSourceNameToEnum(const char *name);
 
-    static const char *kStreamNames[AUDIO_STREAM_CNT+1]; //+1 required as streams start from -1
+    static const char *kStreamNames[AUDIO_STREAM_PUBLIC_CNT+1]; //+1 required as streams start from -1
     audio_stream_type_t streamNameToEnum(const char *name);
 
     // Parse audio_effects.conf
diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
similarity index 76%
rename from services/audiopolicy/AudioPolicyInterfaceImpl.cpp
rename to services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index c06ca72..e9ff8389 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -28,7 +28,8 @@
 
 status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
                                                   audio_policy_dev_state_t state,
-                                                  const char *device_address)
+                                                  const char *device_address,
+                                                  const char *device_name)
 {
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
@@ -46,8 +47,8 @@
 
     ALOGV("setDeviceConnectionState()");
     Mutex::Autolock _l(mLock);
-    return mAudioPolicyManager->setDeviceConnectionState(device,
-                                                      state, device_address);
+    return mAudioPolicyManager->setDeviceConnectionState(device, state,
+                                                         device_address, device_name);
 }
 
 audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState(
@@ -129,7 +130,7 @@
                                     audio_output_flags_t flags,
                                     const audio_offload_info_t *offloadInfo)
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return AUDIO_IO_HANDLE_NONE;
     }
     if (mAudioPolicyManager == NULL) {
@@ -141,25 +142,28 @@
                                     format, channelMask, flags, offloadInfo);
 }
 
-audio_io_handle_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags,
-                                    const audio_offload_info_t *offloadInfo)
+status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
+                                              audio_io_handle_t *output,
+                                              audio_session_t session,
+                                              audio_stream_type_t *stream,
+                                              uint32_t samplingRate,
+                                              audio_format_t format,
+                                              audio_channel_mask_t channelMask,
+                                              audio_output_flags_t flags,
+                                              const audio_offload_info_t *offloadInfo)
 {
     if (mAudioPolicyManager == NULL) {
-        return 0;
+        return NO_INIT;
     }
     ALOGV("getOutput()");
     Mutex::Autolock _l(mLock);
-    return mAudioPolicyManager->getOutputForAttr(attr, samplingRate,
+    return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, samplingRate,
                                     format, channelMask, flags, offloadInfo);
 }
 
 status_t AudioPolicyService::startOutput(audio_io_handle_t output,
                                          audio_stream_type_t stream,
-                                         int session)
+                                         audio_session_t session)
 {
     if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
         return BAD_VALUE;
@@ -186,7 +190,7 @@
 
 status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
                                         audio_stream_type_t stream,
-                                        int session)
+                                        audio_session_t session)
 {
     if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
         return BAD_VALUE;
@@ -201,7 +205,7 @@
 
 status_t  AudioPolicyService::doStopOutput(audio_io_handle_t output,
                                       audio_stream_type_t stream,
-                                      int session)
+                                      audio_session_t session)
 {
     ALOGV("doStopOutput from tid %d", gettid());
     sp<AudioPolicyEffects>audioPolicyEffects;
@@ -220,63 +224,98 @@
     return mAudioPolicyManager->stopOutput(output, stream, session);
 }
 
-void AudioPolicyService::releaseOutput(audio_io_handle_t output)
+void AudioPolicyService::releaseOutput(audio_io_handle_t output,
+                                       audio_stream_type_t stream,
+                                       audio_session_t session)
 {
     if (mAudioPolicyManager == NULL) {
         return;
     }
     ALOGV("releaseOutput()");
-    mOutputCommandThread->releaseOutputCommand(output);
+    mOutputCommandThread->releaseOutputCommand(output, stream, session);
 }
 
-void AudioPolicyService::doReleaseOutput(audio_io_handle_t output)
+void AudioPolicyService::doReleaseOutput(audio_io_handle_t output,
+                                         audio_stream_type_t stream,
+                                         audio_session_t session)
 {
     ALOGV("doReleaseOutput from tid %d", gettid());
     Mutex::Autolock _l(mLock);
-    mAudioPolicyManager->releaseOutput(output);
+    mAudioPolicyManager->releaseOutput(output, stream, session);
 }
 
-audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    int audioSession,
-                                    audio_input_flags_t flags)
+status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
+                                             audio_io_handle_t *input,
+                                             audio_session_t session,
+                                             uint32_t samplingRate,
+                                             audio_format_t format,
+                                             audio_channel_mask_t channelMask,
+                                             audio_input_flags_t flags)
 {
     if (mAudioPolicyManager == NULL) {
-        return 0;
+        return NO_INIT;
     }
     // already checked by client, but double-check in case the client wrapper is bypassed
-    if (inputSource >= AUDIO_SOURCE_CNT && inputSource != AUDIO_SOURCE_HOTWORD &&
-        inputSource != AUDIO_SOURCE_FM_TUNER) {
-        return 0;
+    if (attr->source >= AUDIO_SOURCE_CNT && attr->source != AUDIO_SOURCE_HOTWORD &&
+        attr->source != AUDIO_SOURCE_FM_TUNER) {
+        return BAD_VALUE;
     }
 
-    if (((inputSource == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) ||
-        ((inputSource == AUDIO_SOURCE_FM_TUNER) && !captureFmTunerAllowed())) {
-        return 0;
+    if (((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) ||
+        ((attr->source == AUDIO_SOURCE_FM_TUNER) && !captureFmTunerAllowed())) {
+        return BAD_VALUE;
     }
-    audio_io_handle_t input;
     sp<AudioPolicyEffects>audioPolicyEffects;
+    status_t status;
+    AudioPolicyInterface::input_type_t inputType;
     {
         Mutex::Autolock _l(mLock);
         // the audio_in_acoustics_t parameter is ignored by get_input()
-        input = mAudioPolicyManager->getInput(inputSource, samplingRate,
-                                                       format, channelMask,
-                                                       (audio_session_t)audioSession, flags);
+        status = mAudioPolicyManager->getInputForAttr(attr, input, session,
+                                                     samplingRate, format, channelMask,
+                                                     flags, &inputType);
         audioPolicyEffects = mAudioPolicyEffects;
-    }
-    if (input == 0) {
-        return input;
-    }
-    if (audioPolicyEffects != 0) {
-        // create audio pre processors according to input source
-        status_t status = audioPolicyEffects->addInputEffects(input, inputSource, audioSession);
-        if (status != NO_ERROR && status != ALREADY_EXISTS) {
-            ALOGW("Failed to add effects on input %d", input);
+
+        if (status == NO_ERROR) {
+            // enforce permission (if any) required for each type of input
+            switch (inputType) {
+            case AudioPolicyInterface::API_INPUT_LEGACY:
+                break;
+            case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
+                if (!captureAudioOutputAllowed()) {
+                    ALOGE("getInputForAttr() permission denied: capture not allowed");
+                    status = PERMISSION_DENIED;
+                }
+                break;
+            case AudioPolicyInterface::API_INPUT_MIX_EXT_POLICY_REROUTE:
+                if (!modifyAudioRoutingAllowed()) {
+                    ALOGE("getInputForAttr() permission denied: modify audio routing not allowed");
+                    status = PERMISSION_DENIED;
+                }
+                break;
+            case AudioPolicyInterface::API_INPUT_INVALID:
+            default:
+                LOG_ALWAYS_FATAL("getInputForAttr() encountered an invalid input type %d",
+                        (int)inputType);
+            }
+        }
+
+        if (status != NO_ERROR) {
+            if (status == PERMISSION_DENIED) {
+                mAudioPolicyManager->releaseInput(*input, session);
+            }
+            return status;
         }
     }
-    return input;
+
+    if (audioPolicyEffects != 0) {
+        // create audio pre processors according to input source
+        status_t status = audioPolicyEffects->addInputEffects(*input, attr->source, session);
+        if (status != NO_ERROR && status != ALREADY_EXISTS) {
+            ALOGW("Failed to add effects on input %d", *input);
+        }
+    }
+    return NO_ERROR;
 }
 
 status_t AudioPolicyService::startInput(audio_io_handle_t input,
@@ -332,7 +371,7 @@
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return BAD_VALUE;
     }
     Mutex::Autolock _l(mLock);
@@ -350,7 +389,7 @@
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return BAD_VALUE;
     }
     Mutex::Autolock _l(mLock);
@@ -366,7 +405,7 @@
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
     }
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return BAD_VALUE;
     }
     Mutex::Autolock _l(mLock);
@@ -377,7 +416,7 @@
 
 uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return 0;
     }
     if (mAudioPolicyManager == NULL) {
@@ -390,7 +429,7 @@
 
 audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return AUDIO_DEVICE_NONE;
     }
     if (mAudioPolicyManager == NULL) {
@@ -439,7 +478,7 @@
 
 bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return false;
     }
     if (mAudioPolicyManager == NULL) {
@@ -451,7 +490,7 @@
 
 bool AudioPolicyService::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return false;
     }
     if (mAudioPolicyManager == NULL) {
@@ -606,4 +645,20 @@
     return mAudioPolicyManager->releaseSoundTriggerSession(session);
 }
 
+status_t AudioPolicyService::registerPolicyMixes(Vector<AudioMix> mixes, bool registration)
+{
+    Mutex::Autolock _l(mLock);
+    if(!modifyAudioRoutingAllowed()) {
+        return PERMISSION_DENIED;
+    }
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (registration) {
+        return mAudioPolicyManager->registerPolicyMixes(mixes);
+    } else {
+        return mAudioPolicyManager->unregisterPolicyMixes(mixes);
+    }
+}
+
 }; // namespace android
diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
similarity index 81%
rename from services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
rename to services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
index 09476c1..5a91192 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
@@ -33,7 +33,8 @@
 
 status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
                                                   audio_policy_dev_state_t state,
-                                                  const char *device_address)
+                                                  const char *device_address,
+                                                  const char *device_name __unused)
 {
     if (mpAudioPolicy == NULL) {
         return NO_INIT;
@@ -134,7 +135,7 @@
                                     audio_output_flags_t flags,
                                     const audio_offload_info_t *offloadInfo)
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return AUDIO_IO_HANDLE_NONE;
     }
     if (mpAudioPolicy == NULL) {
@@ -148,9 +149,9 @@
 
 status_t AudioPolicyService::startOutput(audio_io_handle_t output,
                                          audio_stream_type_t stream,
-                                         int session)
+                                         audio_session_t session)
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return BAD_VALUE;
     }
     if (mpAudioPolicy == NULL) {
@@ -176,9 +177,9 @@
 
 status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
                                         audio_stream_type_t stream,
-                                        int session)
+                                        audio_session_t session)
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return BAD_VALUE;
     }
     if (mpAudioPolicy == NULL) {
@@ -191,7 +192,7 @@
 
 status_t  AudioPolicyService::doStopOutput(audio_io_handle_t output,
                                       audio_stream_type_t stream,
-                                      int session)
+                                      audio_session_t session)
 {
     ALOGV("doStopOutput from tid %d", gettid());
     // release audio processors from the stream
@@ -210,64 +211,75 @@
     return mpAudioPolicy->stop_output(mpAudioPolicy, output, stream, session);
 }
 
-void AudioPolicyService::releaseOutput(audio_io_handle_t output)
+void AudioPolicyService::releaseOutput(audio_io_handle_t output,
+                                       audio_stream_type_t stream,
+                                       audio_session_t session)
 {
     if (mpAudioPolicy == NULL) {
         return;
     }
     ALOGV("releaseOutput()");
-    mOutputCommandThread->releaseOutputCommand(output);
+    mOutputCommandThread->releaseOutputCommand(output, stream, session);
 }
 
-void AudioPolicyService::doReleaseOutput(audio_io_handle_t output)
+void AudioPolicyService::doReleaseOutput(audio_io_handle_t output,
+                                         audio_stream_type_t stream __unused,
+                                         audio_session_t session __unused)
 {
     ALOGV("doReleaseOutput from tid %d", gettid());
     Mutex::Autolock _l(mLock);
     mpAudioPolicy->release_output(mpAudioPolicy, output);
 }
 
-audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    int audioSession,
-                                    audio_input_flags_t flags __unused)
+status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
+                                             audio_io_handle_t *input,
+                                             audio_session_t session,
+                                             uint32_t samplingRate,
+                                             audio_format_t format,
+                                             audio_channel_mask_t channelMask,
+                                             audio_input_flags_t flags __unused)
 {
     if (mpAudioPolicy == NULL) {
-        return 0;
+        return NO_INIT;
     }
+
+    audio_source_t inputSource = attr->source;
+
     // already checked by client, but double-check in case the client wrapper is bypassed
     if (inputSource >= AUDIO_SOURCE_CNT && inputSource != AUDIO_SOURCE_HOTWORD &&
         inputSource != AUDIO_SOURCE_FM_TUNER) {
-        return 0;
+        return BAD_VALUE;
+    }
+
+    if (inputSource == AUDIO_SOURCE_DEFAULT) {
+        inputSource = AUDIO_SOURCE_MIC;
     }
 
     if (((inputSource == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) ||
         ((inputSource == AUDIO_SOURCE_FM_TUNER) && !captureFmTunerAllowed())) {
-        return 0;
+        return BAD_VALUE;
     }
 
-    audio_io_handle_t input;
     sp<AudioPolicyEffects>audioPolicyEffects;
     {
         Mutex::Autolock _l(mLock);
         // the audio_in_acoustics_t parameter is ignored by get_input()
-        input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
+        *input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
                                              format, channelMask, (audio_in_acoustics_t) 0);
         audioPolicyEffects = mAudioPolicyEffects;
     }
-    if (input == 0) {
-        return input;
+    if (*input == AUDIO_IO_HANDLE_NONE) {
+        return INVALID_OPERATION;
     }
 
     if (audioPolicyEffects != 0) {
         // create audio pre processors according to input source
-        status_t status = audioPolicyEffects->addInputEffects(input, inputSource, audioSession);
+        status_t status = audioPolicyEffects->addInputEffects(*input, inputSource, session);
         if (status != NO_ERROR && status != ALREADY_EXISTS) {
             ALOGW("Failed to add effects on input %d", input);
         }
     }
-    return input;
+    return NO_ERROR;
 }
 
 status_t AudioPolicyService::startInput(audio_io_handle_t input,
@@ -324,7 +336,7 @@
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return BAD_VALUE;
     }
     Mutex::Autolock _l(mLock);
@@ -342,7 +354,7 @@
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return BAD_VALUE;
     }
     Mutex::Autolock _l(mLock);
@@ -363,7 +375,7 @@
     if (mpAudioPolicy == NULL) {
         return NO_INIT;
     }
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return BAD_VALUE;
     }
     Mutex::Autolock _l(mLock);
@@ -379,7 +391,7 @@
 
 uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return 0;
     }
     if (mpAudioPolicy == NULL) {
@@ -392,7 +404,7 @@
 
 audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return AUDIO_DEVICE_NONE;
     }
     if (mpAudioPolicy == NULL) {
@@ -441,7 +453,7 @@
 
 bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return false;
     }
     if (mpAudioPolicy == NULL) {
@@ -453,7 +465,7 @@
 
 bool AudioPolicyService::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
 {
-    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
         return false;
     }
     if (mpAudioPolicy == NULL) {
@@ -549,26 +561,45 @@
     return INVALID_OPERATION;
 }
 
-audio_io_handle_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    audio_output_flags_t flags,
-                                    const audio_offload_info_t *offloadInfo)
+status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
+                                              audio_io_handle_t *output,
+                                              audio_session_t session __unused,
+                                              audio_stream_type_t *stream,
+                                              uint32_t samplingRate,
+                                              audio_format_t format,
+                                              audio_channel_mask_t channelMask,
+                                              audio_output_flags_t flags,
+                                              const audio_offload_info_t *offloadInfo)
 {
-    audio_stream_type_t stream = audio_attributes_to_stream_type(attr);
-
-    return getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo);
+    if (attr != NULL) {
+        *stream = audio_attributes_to_stream_type(attr);
+    } else {
+        if (*stream == AUDIO_STREAM_DEFAULT) {
+            return BAD_VALUE;
+        }
+    }
+    *output = getOutput(*stream, samplingRate, format, channelMask,
+                                          flags, offloadInfo);
+    if (*output == AUDIO_IO_HANDLE_NONE) {
+        return INVALID_OPERATION;
+    }
+    return NO_ERROR;
 }
 
-status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session,
-                                       audio_io_handle_t *ioHandle,
-                                       audio_devices_t *device)
+status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session __unused,
+                                       audio_io_handle_t *ioHandle __unused,
+                                       audio_devices_t *device __unused)
 {
     return INVALID_OPERATION;
 }
 
-status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session)
+status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session __unused)
+{
+    return INVALID_OPERATION;
+}
+
+status_t AudioPolicyService::registerPolicyMixes(Vector<AudioMix> mixes __unused,
+                                                 bool registration __unused)
 {
     return INVALID_OPERATION;
 }
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
similarity index 97%
rename from services/audiopolicy/AudioPolicyService.cpp
rename to services/audiopolicy/service/AudioPolicyService.cpp
index dd4067f..eb9116d 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -35,6 +35,7 @@
 #include <hardware_legacy/power.h>
 #include <media/AudioEffect.h>
 #include <media/EffectsFactoryApi.h>
+#include <media/AudioParameter.h>
 
 #include <hardware/hardware.h>
 #include <system/audio.h>
@@ -149,7 +150,7 @@
 void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client)
 {
 
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mNotificationClientsLock);
 
     uid_t uid = IPCThreadState::self()->getCallingUid();
     if (mNotificationClients.indexOfKey(uid) < 0) {
@@ -160,7 +161,7 @@
 
         mNotificationClients.add(uid, notificationClient);
 
-        sp<IBinder> binder = client->asBinder();
+        sp<IBinder> binder = IInterface::asBinder(client);
         binder->linkToDeath(notificationClient);
     }
 }
@@ -168,14 +169,17 @@
 // removeNotificationClient() is called when the client process dies.
 void AudioPolicyService::removeNotificationClient(uid_t uid)
 {
-    Mutex::Autolock _l(mLock);
-
-    mNotificationClients.removeItem(uid);
-
+    {
+        Mutex::Autolock _l(mNotificationClientsLock);
+        mNotificationClients.removeItem(uid);
+    }
 #ifndef USE_LEGACY_AUDIO_POLICY
+    {
+        Mutex::Autolock _l(mLock);
         if (mAudioPolicyManager) {
             mAudioPolicyManager->clearAudioPatches(uid);
         }
+    }
 #endif
 }
 
@@ -186,7 +190,7 @@
 
 void AudioPolicyService::doOnAudioPortListUpdate()
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mNotificationClientsLock);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
         mNotificationClients.valueAt(i)->onAudioPortListUpdate();
     }
@@ -212,7 +216,7 @@
 
 void AudioPolicyService::doOnAudioPatchListUpdate()
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mNotificationClientsLock);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
         mNotificationClients.valueAt(i)->onAudioPatchListUpdate();
     }
@@ -454,7 +458,7 @@
                         break;
                     }
                     mLock.unlock();
-                    svc->doReleaseOutput(data->mIO);
+                    svc->doReleaseOutput(data->mIO, data->mStream, data->mSession);
                     mLock.lock();
                     }break;
                 case CREATE_AUDIO_PATCH: {
@@ -651,7 +655,7 @@
 
 void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output,
                                                                audio_stream_type_t stream,
-                                                               int session)
+                                                               audio_session_t session)
 {
     sp<AudioCommand> command = new AudioCommand();
     command->mCommand = STOP_OUTPUT;
@@ -664,12 +668,16 @@
     sendCommand(command);
 }
 
-void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output)
+void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output,
+                                                                  audio_stream_type_t stream,
+                                                                  audio_session_t session)
 {
     sp<AudioCommand> command = new AudioCommand();
     command->mCommand = RELEASE_OUTPUT;
     sp<ReleaseOutputData> data = new ReleaseOutputData();
     data->mIO = output;
+    data->mStream = stream;
+    data->mSession = session;
     command->mParam = data;
     ALOGV("AudioCommandThread() adding release output %d", output);
     sendCommand(command);
@@ -900,8 +908,10 @@
     }
     removedCommands.clear();
 
-    // Disable wait for status if delay is not 0
-    if (delayMs != 0) {
+    // Disable wait for status if delay is not 0.
+    // Except for create audio patch command because the returned patch handle
+    // is needed by audio policy manager
+    if (delayMs != 0 && command->mCommand != CREATE_AUDIO_PATCH) {
         command->mWaitStatus = false;
     }
 
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
similarity index 90%
rename from services/audiopolicy/AudioPolicyService.h
rename to services/audiopolicy/service/AudioPolicyService.h
index 4e68ab1..0378384 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -30,9 +30,12 @@
 #include <media/IAudioPolicyService.h>
 #include <media/ToneGenerator.h>
 #include <media/AudioEffect.h>
+#include <media/AudioPolicy.h>
+#ifdef USE_LEGACY_AUDIO_POLICY
 #include <hardware_legacy/AudioPolicyInterface.h>
+#endif
 #include "AudioPolicyEffects.h"
-#include "AudioPolicyManager.h"
+#include "managerdefault/AudioPolicyManager.h"
 
 
 namespace android {
@@ -58,7 +61,8 @@
 
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
-                                              const char *device_address);
+                                              const char *device_address,
+                                              const char *device_name);
     virtual audio_policy_dev_state_t getDeviceConnectionState(
                                                                 audio_devices_t device,
                                                                 const char *device_address);
@@ -72,25 +76,31 @@
                                         audio_output_flags_t flags =
                                                 AUDIO_OUTPUT_FLAG_NONE,
                                         const audio_offload_info_t *offloadInfo = NULL);
-    virtual audio_io_handle_t getOutputForAttr(const audio_attributes_t *attr,
-                                            uint32_t samplingRate = 0,
-                                            audio_format_t format = AUDIO_FORMAT_DEFAULT,
-                                            audio_channel_mask_t channelMask = 0,
-                                            audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
-                                            const audio_offload_info_t *offloadInfo = NULL);
+    virtual status_t getOutputForAttr(const audio_attributes_t *attr,
+                                      audio_io_handle_t *output,
+                                      audio_session_t session,
+                                      audio_stream_type_t *stream,
+                                      uint32_t samplingRate = 0,
+                                      audio_format_t format = AUDIO_FORMAT_DEFAULT,
+                                      audio_channel_mask_t channelMask = 0,
+                                      audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+                                      const audio_offload_info_t *offloadInfo = NULL);
     virtual status_t startOutput(audio_io_handle_t output,
                                  audio_stream_type_t stream,
-                                 int session = 0);
+                                 audio_session_t session);
     virtual status_t stopOutput(audio_io_handle_t output,
                                 audio_stream_type_t stream,
-                                int session = 0);
-    virtual void releaseOutput(audio_io_handle_t output);
-    virtual audio_io_handle_t getInput(audio_source_t inputSource,
-                                    uint32_t samplingRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    int audioSession,
-                                    audio_input_flags_t flags);
+                                audio_session_t session);
+    virtual void releaseOutput(audio_io_handle_t output,
+                               audio_stream_type_t stream,
+                               audio_session_t session);
+    virtual status_t getInputForAttr(const audio_attributes_t *attr,
+                                     audio_io_handle_t *input,
+                                     audio_session_t session,
+                                     uint32_t samplingRate,
+                                     audio_format_t format,
+                                     audio_channel_mask_t channelMask,
+                                     audio_input_flags_t flags);
     virtual status_t startInput(audio_io_handle_t input,
                                 audio_session_t session);
     virtual status_t stopInput(audio_io_handle_t input,
@@ -179,10 +189,14 @@
 
     virtual audio_mode_t getPhoneState();
 
+    virtual status_t registerPolicyMixes(Vector<AudioMix> mixes, bool registration);
+
             status_t doStopOutput(audio_io_handle_t output,
                                   audio_stream_type_t stream,
-                                  int session = 0);
-            void doReleaseOutput(audio_io_handle_t output);
+                                  audio_session_t session);
+            void doReleaseOutput(audio_io_handle_t output,
+                                 audio_stream_type_t stream,
+                                 audio_session_t session);
 
             status_t clientCreateAudioPatch(const struct audio_patch *patch,
                                       audio_patch_handle_t *handle,
@@ -250,8 +264,10 @@
                     status_t    voiceVolumeCommand(float volume, int delayMs = 0);
                     void        stopOutputCommand(audio_io_handle_t output,
                                                   audio_stream_type_t stream,
-                                                  int session);
-                    void        releaseOutputCommand(audio_io_handle_t output);
+                                                  audio_session_t session);
+                    void        releaseOutputCommand(audio_io_handle_t output,
+                                                     audio_stream_type_t stream,
+                                                     audio_session_t session);
                     status_t    sendCommand(sp<AudioCommand>& command, int delayMs = 0);
                     void        insertCommand_l(sp<AudioCommand>& command, int delayMs = 0);
                     status_t    createAudioPatchCommand(const struct audio_patch *patch,
@@ -321,12 +337,14 @@
         public:
             audio_io_handle_t mIO;
             audio_stream_type_t mStream;
-            int mSession;
+            audio_session_t mSession;
         };
 
         class ReleaseOutputData : public AudioCommandData {
         public:
             audio_io_handle_t mIO;
+            audio_stream_type_t mStream;
+            audio_session_t mSession;
         };
 
         class CreateAudioPatchData : public AudioCommandData {
@@ -495,7 +513,7 @@
     AudioPolicyClient *mAudioPolicyClient;
 
     DefaultKeyedVector< uid_t, sp<NotificationClient> >    mNotificationClients;
-
+    Mutex mNotificationClientsLock;  // protects mNotificationClients
     // Manage all effects configured in audio_effects.conf
     sp<AudioPolicyEffects> mAudioPolicyEffects;
     audio_mode_t mPhoneState;
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index e184d97..de841c8 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -23,8 +23,10 @@
 LOCAL_SRC_FILES:=               \
     CameraService.cpp \
     CameraDeviceFactory.cpp \
+    CameraFlashlight.cpp \
     common/Camera2ClientBase.cpp \
     common/CameraDeviceBase.cpp \
+    common/CameraModule.cpp \
     common/FrameProcessorBase.cpp \
     api1/CameraClient.cpp \
     api1/Camera2Client.cpp \
@@ -52,6 +54,7 @@
     device3/StatusTracker.cpp \
     gui/RingBufferConsumer.cpp \
     utils/CameraTraces.cpp \
+    utils/AutoConditionLock.cpp \
 
 LOCAL_SHARED_LIBRARIES:= \
     libui \
diff --git a/services/camera/libcameraservice/CameraDeviceFactory.cpp b/services/camera/libcameraservice/CameraDeviceFactory.cpp
index bfef50e..6589e27 100644
--- a/services/camera/libcameraservice/CameraDeviceFactory.cpp
+++ b/services/camera/libcameraservice/CameraDeviceFactory.cpp
@@ -48,6 +48,7 @@
         case CAMERA_DEVICE_API_VERSION_3_0:
         case CAMERA_DEVICE_API_VERSION_3_1:
         case CAMERA_DEVICE_API_VERSION_3_2:
+        case CAMERA_DEVICE_API_VERSION_3_3:
             device = new Camera3Device(cameraId);
             break;
         default:
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
new file mode 100644
index 0000000..6fda9b2
--- /dev/null
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -0,0 +1,889 @@
+/*
+ * 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 "CameraFlashlight"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+// #define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <cutils/properties.h>
+
+#include "camera/CameraMetadata.h"
+#include "CameraFlashlight.h"
+#include "gui/IGraphicBufferConsumer.h"
+#include "gui/BufferQueue.h"
+#include "camera/camera2/CaptureRequest.h"
+#include "CameraDeviceFactory.h"
+
+
+namespace android {
+
+/////////////////////////////////////////////////////////////////////
+// CameraFlashlight implementation begins
+// used by camera service to control flashflight.
+/////////////////////////////////////////////////////////////////////
+CameraFlashlight::CameraFlashlight(CameraModule& cameraModule,
+        const camera_module_callbacks_t& callbacks) :
+        mCameraModule(&cameraModule),
+        mCallbacks(&callbacks),
+        mFlashlightMapInitialized(false) {
+}
+
+CameraFlashlight::~CameraFlashlight() {
+}
+
+status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
+    ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
+            cameraId.string());
+    if (mFlashControl != NULL) {
+        return INVALID_OPERATION;
+    }
+
+    status_t res = OK;
+
+    if (mCameraModule->getRawModule()->module_api_version >=
+            CAMERA_MODULE_API_VERSION_2_4) {
+        mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks);
+        if (mFlashControl == NULL) {
+            ALOGV("%s: cannot create flash control for module api v2.4+",
+                     __FUNCTION__);
+            return NO_MEMORY;
+        }
+    } else {
+        uint32_t deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
+
+        if (mCameraModule->getRawModule()->module_api_version >=
+                CAMERA_MODULE_API_VERSION_2_0) {
+            camera_info info;
+            res = mCameraModule->getCameraInfo(
+                    atoi(String8(cameraId).string()), &info);
+            if (res) {
+                ALOGE("%s: failed to get camera info for camera %s",
+                        __FUNCTION__, cameraId.string());
+                return res;
+            }
+            deviceVersion = info.device_version;
+        }
+
+        if (deviceVersion >= CAMERA_DEVICE_API_VERSION_2_0) {
+            CameraDeviceClientFlashControl *flashControl =
+                    new CameraDeviceClientFlashControl(*mCameraModule,
+                                                       *mCallbacks);
+            if (!flashControl) {
+                return NO_MEMORY;
+            }
+
+            mFlashControl = flashControl;
+        } else {
+            mFlashControl =
+                    new CameraHardwareInterfaceFlashControl(*mCameraModule,
+                                                            *mCallbacks);
+        }
+    }
+
+    return OK;
+}
+
+status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
+    if (!mFlashlightMapInitialized) {
+        ALOGE("%s: findFlashUnits() must be called before this method.");
+        return NO_INIT;
+    }
+
+    ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
+            cameraId.string(), enabled);
+
+    status_t res = OK;
+    Mutex::Autolock l(mLock);
+
+    if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
+        // This case is needed to avoid state corruption during the following call sequence:
+        // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
+        // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
+        // CameraService::setTorchMode for camera ID 0 continues, calls
+        //        CameraFlashlight::setTorchMode
+
+        // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
+        // to avoid other similar race conditions.
+        ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
+                __FUNCTION__, cameraId.string());
+        return -EBUSY;
+    }
+
+    if (mFlashControl == NULL) {
+        if (enabled == false) {
+            return OK;
+        }
+
+        res = createFlashlightControl(cameraId);
+        if (res) {
+            return res;
+        }
+        res =  mFlashControl->setTorchMode(cameraId, enabled);
+        return res;
+    }
+
+    // if flash control already exists, turning on torch mode may fail if it's
+    // tied to another camera device for module v2.3 and below.
+    res = mFlashControl->setTorchMode(cameraId, enabled);
+    if (res == BAD_INDEX) {
+        // flash control is tied to another camera device, need to close it and
+        // try again.
+        mFlashControl.clear();
+        res = createFlashlightControl(cameraId);
+        if (res) {
+            return res;
+        }
+        res = mFlashControl->setTorchMode(cameraId, enabled);
+    }
+
+    return res;
+}
+
+status_t CameraFlashlight::findFlashUnits() {
+    Mutex::Autolock l(mLock);
+    status_t res;
+    int32_t numCameras = mCameraModule->getNumberOfCameras();
+
+    mHasFlashlightMap.clear();
+    mFlashlightMapInitialized = false;
+
+    for (int32_t i = 0; i < numCameras; i++) {
+        bool hasFlash = false;
+        String8 id = String8::format("%d", i);
+
+        res = createFlashlightControl(id);
+        if (res) {
+            ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
+                    id.string());
+        } else {
+            res = mFlashControl->hasFlashUnit(id, &hasFlash);
+            if (res == -EUSERS || res == -EBUSY) {
+                ALOGE("%s: failed to check if camera %s has a flash unit. Some "
+                        "camera devices may be opened", __FUNCTION__,
+                        id.string());
+                return res;
+            } else if (res) {
+                ALOGE("%s: failed to check if camera %s has a flash unit. %s"
+                        " (%d)", __FUNCTION__, id.string(), strerror(-res),
+                        res);
+            }
+
+            mFlashControl.clear();
+        }
+        mHasFlashlightMap.add(id, hasFlash);
+    }
+
+    mFlashlightMapInitialized = true;
+    return OK;
+}
+
+bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
+    status_t res;
+
+    Mutex::Autolock l(mLock);
+    return hasFlashUnitLocked(cameraId);
+}
+
+bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
+    if (!mFlashlightMapInitialized) {
+        ALOGE("%s: findFlashUnits() must be called before this method.");
+        return false;
+    }
+
+    ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
+    if (index == NAME_NOT_FOUND) {
+        ALOGE("%s: camera %s not present when findFlashUnits() was called",
+                __FUNCTION__, cameraId.string());
+        return false;
+    }
+
+    return mHasFlashlightMap.valueAt(index);
+}
+
+status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
+    ALOGV("%s: prepare for device open", __FUNCTION__);
+
+    Mutex::Autolock l(mLock);
+    if (!mFlashlightMapInitialized) {
+        ALOGE("%s: findFlashUnits() must be called before this method.");
+        return NO_INIT;
+    }
+
+    if (mCameraModule->getRawModule()->module_api_version <
+            CAMERA_MODULE_API_VERSION_2_4) {
+        // framework is going to open a camera device, all flash light control
+        // should be closed for backward compatible support.
+        mFlashControl.clear();
+
+        if (mOpenedCameraIds.size() == 0) {
+            // notify torch unavailable for all cameras with a flash
+            int numCameras = mCameraModule->getNumberOfCameras();
+            for (int i = 0; i < numCameras; i++) {
+                if (hasFlashUnitLocked(String8::format("%d", i))) {
+                    mCallbacks->torch_mode_status_change(mCallbacks,
+                            String8::format("%d", i).string(),
+                            TORCH_MODE_STATUS_NOT_AVAILABLE);
+                }
+            }
+        }
+
+        // close flash control that may be opened by calling hasFlashUnitLocked.
+        mFlashControl.clear();
+    }
+
+    if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
+        mOpenedCameraIds.add(cameraId);
+    }
+
+    return OK;
+}
+
+status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
+    ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
+
+    Mutex::Autolock l(mLock);
+    if (!mFlashlightMapInitialized) {
+        ALOGE("%s: findFlashUnits() must be called before this method.");
+        return NO_INIT;
+    }
+
+    ssize_t index = mOpenedCameraIds.indexOf(cameraId);
+    if (index == NAME_NOT_FOUND) {
+        ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
+                cameraId.string());
+    } else {
+        mOpenedCameraIds.removeAt(index);
+    }
+
+    // Cannot do anything until all cameras are closed.
+    if (mOpenedCameraIds.size() != 0)
+        return OK;
+
+    if (mCameraModule->getRawModule()->module_api_version <
+            CAMERA_MODULE_API_VERSION_2_4) {
+        // notify torch available for all cameras with a flash
+        int numCameras = mCameraModule->getNumberOfCameras();
+        for (int i = 0; i < numCameras; i++) {
+            if (hasFlashUnitLocked(String8::format("%d", i))) {
+                mCallbacks->torch_mode_status_change(mCallbacks,
+                        String8::format("%d", i).string(),
+                        TORCH_MODE_STATUS_AVAILABLE_OFF);
+            }
+        }
+    }
+
+    return OK;
+}
+// CameraFlashlight implementation ends
+
+
+FlashControlBase::~FlashControlBase() {
+}
+
+/////////////////////////////////////////////////////////////////////
+// ModuleFlashControl implementation begins
+// Flash control for camera module v2.4 and above.
+/////////////////////////////////////////////////////////////////////
+ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
+        const camera_module_callbacks_t& callbacks) :
+    mCameraModule(&cameraModule) {
+}
+
+ModuleFlashControl::~ModuleFlashControl() {
+}
+
+status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
+    if (!hasFlash) {
+        return BAD_VALUE;
+    }
+
+    *hasFlash = false;
+    Mutex::Autolock l(mLock);
+
+    camera_info info;
+    status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
+            &info);
+    if (res != 0) {
+        return res;
+    }
+
+    CameraMetadata metadata;
+    metadata = info.static_camera_characteristics;
+    camera_metadata_entry flashAvailable =
+            metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
+    if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
+        *hasFlash = true;
+    }
+
+    return OK;
+}
+
+status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
+    ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
+            cameraId.string(), enabled);
+
+    Mutex::Autolock l(mLock);
+    return mCameraModule->setTorchMode(cameraId.string(), enabled);
+}
+// ModuleFlashControl implementation ends
+
+/////////////////////////////////////////////////////////////////////
+// CameraDeviceClientFlashControl implementation begins
+// Flash control for camera module <= v2.3 and camera HAL v2-v3
+/////////////////////////////////////////////////////////////////////
+CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
+        CameraModule& cameraModule,
+        const camera_module_callbacks_t& callbacks) :
+        mCameraModule(&cameraModule),
+        mCallbacks(&callbacks),
+        mTorchEnabled(false),
+        mMetadata(NULL),
+        mStreaming(false) {
+}
+
+CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
+    disconnectCameraDevice();
+    if (mMetadata) {
+        delete mMetadata;
+    }
+
+    mAnw.clear();
+    mSurfaceTexture.clear();
+    mProducer.clear();
+    mConsumer.clear();
+
+    if (mTorchEnabled) {
+        if (mCallbacks) {
+            ALOGV("%s: notify the framework that torch was turned off",
+                    __FUNCTION__);
+            mCallbacks->torch_mode_status_change(mCallbacks,
+                    mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
+        }
+    }
+}
+
+status_t CameraDeviceClientFlashControl::initializeSurface(
+        sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
+    status_t res;
+    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+
+    mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
+            true, true);
+    if (mSurfaceTexture == NULL) {
+        return NO_MEMORY;
+    }
+
+    int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+    res = mSurfaceTexture->setDefaultBufferSize(width, height);
+    if (res) {
+        return res;
+    }
+    res = mSurfaceTexture->setDefaultBufferFormat(format);
+    if (res) {
+        return res;
+    }
+
+    mAnw = new Surface(mProducer, /*useAsync*/ true);
+    if (mAnw == NULL) {
+        return NO_MEMORY;
+    }
+    res = device->createStream(mAnw, width, height, format,
+            HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
+    if (res) {
+        return res;
+    }
+
+    res = device->configureStreams();
+    if (res) {
+        return res;
+    }
+
+    return res;
+}
+
+status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
+        const camera_info& info, int32_t *width, int32_t *height) {
+    if (!width || !height) {
+        return BAD_VALUE;
+    }
+
+    int32_t w = INT32_MAX;
+    int32_t h = 1;
+
+    CameraMetadata metadata;
+    metadata = info.static_camera_characteristics;
+    camera_metadata_entry streamConfigs =
+            metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+    for (size_t i = 0; i < streamConfigs.count; i += 4) {
+        int32_t fmt = streamConfigs.data.i32[i];
+        if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
+            int32_t ww = streamConfigs.data.i32[i + 1];
+            int32_t hh = streamConfigs.data.i32[i + 2];
+
+            if (w * h > ww * hh) {
+                w = ww;
+                h = hh;
+            }
+        }
+    }
+
+    // if stream configuration is not found, try available processed sizes.
+    if (streamConfigs.count == 0) {
+        camera_metadata_entry availableProcessedSizes =
+            metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
+        for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
+            int32_t ww = availableProcessedSizes.data.i32[i];
+            int32_t hh = availableProcessedSizes.data.i32[i + 1];
+            if (w * h > ww * hh) {
+                w = ww;
+                h = hh;
+            }
+        }
+    }
+
+    if (w == INT32_MAX) {
+        return NAME_NOT_FOUND;
+    }
+
+    *width = w;
+    *height = h;
+
+    return OK;
+}
+
+status_t CameraDeviceClientFlashControl::connectCameraDevice(
+        const String8& cameraId) {
+    camera_info info;
+    status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
+    if (res != 0) {
+        ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
+                cameraId.string());
+        return res;
+    }
+
+    sp<CameraDeviceBase> device =
+            CameraDeviceFactory::createDevice(atoi(cameraId.string()));
+    if (device == NULL) {
+        return NO_MEMORY;
+    }
+
+    res = device->initialize(mCameraModule);
+    if (res) {
+        return res;
+    }
+
+    int32_t width, height;
+    res = getSmallestSurfaceSize(info, &width, &height);
+    if (res) {
+        return res;
+    }
+    res = initializeSurface(device, width, height);
+    if (res) {
+        return res;
+    }
+
+    mCameraId = cameraId;
+    mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
+    mDevice = device;
+
+    return OK;
+}
+
+status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
+    if (mDevice != NULL) {
+        mDevice->disconnect();
+        mDevice.clear();
+    }
+
+    return OK;
+}
+
+
+
+status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
+        bool *hasFlash) {
+    ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
+            cameraId.string());
+
+    Mutex::Autolock l(mLock);
+    return hasFlashUnitLocked(cameraId, hasFlash);
+
+}
+
+status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
+        const String8& cameraId, bool *hasFlash) {
+    if (!hasFlash) {
+        return BAD_VALUE;
+    }
+
+    camera_info info;
+    status_t res = mCameraModule->getCameraInfo(
+            atoi(cameraId.string()), &info);
+    if (res != 0) {
+        ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
+                cameraId.string());
+        return res;
+    }
+
+    CameraMetadata metadata;
+    metadata = info.static_camera_characteristics;
+    camera_metadata_entry flashAvailable =
+            metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
+    if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
+        *hasFlash = true;
+    }
+
+    return OK;
+}
+
+status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
+    status_t res;
+
+    if (mMetadata == NULL) {
+        mMetadata = new CameraMetadata();
+        if (mMetadata == NULL) {
+            return NO_MEMORY;
+        }
+        res = mDevice->createDefaultRequest(
+                CAMERA3_TEMPLATE_PREVIEW, mMetadata);
+        if (res) {
+            return res;
+        }
+    }
+
+    uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
+    mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
+    mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
+
+    uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
+    mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
+
+    int32_t requestId = 0;
+    mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
+
+    if (mStreaming) {
+        res = mDevice->setStreamingRequest(*mMetadata);
+    } else {
+        res = mDevice->capture(*mMetadata);
+    }
+    return res;
+}
+
+
+
+
+status_t CameraDeviceClientFlashControl::setTorchMode(
+        const String8& cameraId, bool enabled) {
+    bool hasFlash = false;
+
+    Mutex::Autolock l(mLock);
+    status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
+
+    // pre-check
+    if (enabled) {
+        // invalid camera?
+        if (res) {
+            return -EINVAL;
+        }
+        // no flash unit?
+        if (!hasFlash) {
+            return -ENOSYS;
+        }
+        // already opened for a different device?
+        if (mDevice != NULL && cameraId != mCameraId) {
+            return BAD_INDEX;
+        }
+    } else if (mDevice == NULL || cameraId != mCameraId) {
+        // disabling the torch mode of an un-opened or different device.
+        return OK;
+    } else {
+        // disabling the torch mode of currently opened device
+        disconnectCameraDevice();
+        mTorchEnabled = false;
+        mCallbacks->torch_mode_status_change(mCallbacks,
+            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
+        return OK;
+    }
+
+    if (mDevice == NULL) {
+        res = connectCameraDevice(cameraId);
+        if (res) {
+            return res;
+        }
+    }
+
+    res = submitTorchEnabledRequest();
+    if (res) {
+        return res;
+    }
+
+    mTorchEnabled = true;
+    mCallbacks->torch_mode_status_change(mCallbacks,
+            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
+    return OK;
+}
+// CameraDeviceClientFlashControl implementation ends
+
+
+/////////////////////////////////////////////////////////////////////
+// CameraHardwareInterfaceFlashControl implementation begins
+// Flash control for camera module <= v2.3 and camera HAL v1
+/////////////////////////////////////////////////////////////////////
+CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
+        CameraModule& cameraModule,
+        const camera_module_callbacks_t& callbacks) :
+        mCameraModule(&cameraModule),
+        mCallbacks(&callbacks),
+        mTorchEnabled(false) {
+
+}
+
+CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
+    disconnectCameraDevice();
+
+    mAnw.clear();
+    mSurfaceTexture.clear();
+    mProducer.clear();
+    mConsumer.clear();
+
+    if (mTorchEnabled) {
+        if (mCallbacks) {
+            ALOGV("%s: notify the framework that torch was turned off",
+                    __FUNCTION__);
+            mCallbacks->torch_mode_status_change(mCallbacks,
+                    mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
+        }
+    }
+}
+
+status_t CameraHardwareInterfaceFlashControl::setTorchMode(
+        const String8& cameraId, bool enabled) {
+    Mutex::Autolock l(mLock);
+
+    // pre-check
+    status_t res;
+    if (enabled) {
+        bool hasFlash = false;
+        res = hasFlashUnitLocked(cameraId, &hasFlash);
+        // invalid camera?
+        if (res) {
+            // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
+            // another camera device.
+            return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
+        }
+        // no flash unit?
+        if (!hasFlash) {
+            return -ENOSYS;
+        }
+    } else if (mDevice == NULL || cameraId != mCameraId) {
+        // disabling the torch mode of an un-opened or different device.
+        return OK;
+    } else {
+        // disabling the torch mode of currently opened device
+        disconnectCameraDevice();
+        mTorchEnabled = false;
+        mCallbacks->torch_mode_status_change(mCallbacks,
+            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
+        return OK;
+    }
+
+    res = startPreviewAndTorch();
+    if (res) {
+        return res;
+    }
+
+    mTorchEnabled = true;
+    mCallbacks->torch_mode_status_change(mCallbacks,
+            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
+    return OK;
+}
+
+status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
+        const String8& cameraId, bool *hasFlash) {
+    Mutex::Autolock l(mLock);
+    return hasFlashUnitLocked(cameraId, hasFlash);
+}
+
+status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
+        const String8& cameraId, bool *hasFlash) {
+    if (!hasFlash) {
+        return BAD_VALUE;
+    }
+
+    status_t res;
+    if (mDevice == NULL) {
+        res = connectCameraDevice(cameraId);
+        if (res) {
+            return res;
+        }
+    }
+
+    if (cameraId != mCameraId) {
+        return BAD_INDEX;
+    }
+
+    const char *flashMode =
+            mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
+    if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
+        *hasFlash = true;
+    } else {
+        *hasFlash = false;
+    }
+
+    return OK;
+}
+
+status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
+    status_t res = OK;
+    res = mDevice->startPreview();
+    if (res) {
+        ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
+                strerror(-res), res);
+        return res;
+    }
+
+    mParameters.set(CameraParameters::KEY_FLASH_MODE,
+            CameraParameters::FLASH_MODE_TORCH);
+
+    return mDevice->setParameters(mParameters);
+}
+
+status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
+        int32_t *width, int32_t *height) {
+    if (!width || !height) {
+        return BAD_VALUE;
+    }
+
+    int32_t w = INT32_MAX;
+    int32_t h = 1;
+    Vector<Size> sizes;
+
+    mParameters.getSupportedPreviewSizes(sizes);
+    for (size_t i = 0; i < sizes.size(); i++) {
+        Size s = sizes[i];
+        if (w * h > s.width * s.height) {
+            w = s.width;
+            h = s.height;
+        }
+    }
+
+    if (w == INT32_MAX) {
+        return NAME_NOT_FOUND;
+    }
+
+    *width = w;
+    *height = h;
+
+    return OK;
+}
+
+status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
+        sp<CameraHardwareInterface> device, int32_t width, int32_t height) {
+    status_t res;
+    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+
+    mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
+            true, true);
+    if (mSurfaceTexture == NULL) {
+        return NO_MEMORY;
+    }
+
+    int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+    res = mSurfaceTexture->setDefaultBufferSize(width, height);
+    if (res) {
+        return res;
+    }
+    res = mSurfaceTexture->setDefaultBufferFormat(format);
+    if (res) {
+        return res;
+    }
+
+    mAnw = new Surface(mProducer, /*useAsync*/ true);
+    if (mAnw == NULL) {
+        return NO_MEMORY;
+    }
+
+    res = native_window_api_connect(mAnw.get(), NATIVE_WINDOW_API_CAMERA);
+    if (res) {
+        ALOGE("%s: Unable to connect to native window", __FUNCTION__);
+        return res;
+    }
+
+    return device->setPreviewWindow(mAnw);
+}
+
+status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
+        const String8& cameraId) {
+    sp<CameraHardwareInterface> device =
+            new CameraHardwareInterface(cameraId.string());
+
+    status_t res = device->initialize(mCameraModule);
+    if (res) {
+        ALOGE("%s: initializing camera %s failed", __FUNCTION__,
+                cameraId.string());
+        return res;
+    }
+
+    // need to set __get_memory in set_callbacks().
+    device->setCallbacks(NULL, NULL, NULL, NULL);
+
+    mParameters = device->getParameters();
+
+    int32_t width, height;
+    res = getSmallestSurfaceSize(&width, &height);
+    if (res) {
+        ALOGE("%s: failed to get smallest surface size for camera %s",
+                __FUNCTION__, cameraId.string());
+        return res;
+    }
+
+    res = initializePreviewWindow(device, width, height);
+    if (res) {
+        ALOGE("%s: failed to initialize preview window for camera %s",
+                __FUNCTION__, cameraId.string());
+        return res;
+    }
+
+    mCameraId = cameraId;
+    mDevice = device;
+    return OK;
+}
+
+status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
+    if (mDevice == NULL) {
+        return OK;
+    }
+
+    mParameters.set(CameraParameters::KEY_FLASH_MODE,
+            CameraParameters::FLASH_MODE_OFF);
+    mDevice->setParameters(mParameters);
+    mDevice->stopPreview();
+    status_t res = native_window_api_disconnect(mAnw.get(),
+            NATIVE_WINDOW_API_CAMERA);
+    if (res) {
+        ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+    }
+    mDevice->setPreviewWindow(NULL);
+    mDevice->release();
+
+    return OK;
+}
+// CameraHardwareInterfaceFlashControl implementation ends
+
+}
diff --git a/services/camera/libcameraservice/CameraFlashlight.h b/services/camera/libcameraservice/CameraFlashlight.h
new file mode 100644
index 0000000..30f01f0
--- /dev/null
+++ b/services/camera/libcameraservice/CameraFlashlight.h
@@ -0,0 +1,225 @@
+/*
+ * 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_SERVERS_CAMERA_CAMERAFLASHLIGHT_H
+#define ANDROID_SERVERS_CAMERA_CAMERAFLASHLIGHT_H
+
+#include "hardware/camera_common.h"
+#include "utils/KeyedVector.h"
+#include "utils/SortedVector.h"
+#include "gui/GLConsumer.h"
+#include "gui/Surface.h"
+#include "common/CameraDeviceBase.h"
+#include "device1/CameraHardwareInterface.h"
+
+namespace android {
+
+/**
+ * FlashControlBase is a base class for flash control. It defines the functions
+ * that a flash control for each camera module/device version should implement.
+ */
+class FlashControlBase : public virtual VirtualLightRefBase {
+    public:
+        virtual ~FlashControlBase();
+
+        // Whether a camera device has a flash unit. Calling this function may
+        // cause the torch mode to be turned off in HAL v1 devices. If
+        // previously-on torch mode is turned off,
+        // callbacks.torch_mode_status_change() should be invoked.
+        virtual status_t hasFlashUnit(const String8& cameraId,
+                    bool *hasFlash) = 0;
+
+        // set the torch mode to on or off.
+        virtual status_t setTorchMode(const String8& cameraId,
+                    bool enabled) = 0;
+};
+
+/**
+ * CameraFlashlight can be used by camera service to control flashflight.
+ */
+class CameraFlashlight : public virtual VirtualLightRefBase {
+    public:
+        CameraFlashlight(CameraModule& cameraModule,
+                const camera_module_callbacks_t& callbacks);
+        virtual ~CameraFlashlight();
+
+        // Find all flash units. This must be called before other methods. All
+        // camera devices must be closed when it's called because HAL v1 devices
+        // need to be opened to query available flash modes.
+        status_t findFlashUnits();
+
+        // Whether a camera device has a flash unit. Before findFlashUnits() is
+        // called, this function always returns false.
+        bool hasFlashUnit(const String8& cameraId);
+
+        // set the torch mode to on or off.
+        status_t setTorchMode(const String8& cameraId, bool enabled);
+
+        // Notify CameraFlashlight that camera service is going to open a camera
+        // device. CameraFlashlight will free the resources that may cause the
+        // camera open to fail. Camera service must call this function before
+        // opening a camera device.
+        status_t prepareDeviceOpen(const String8& cameraId);
+
+        // Notify CameraFlashlight that camera service has closed a camera
+        // device. CameraFlashlight may invoke callbacks for torch mode
+        // available depending on the implementation.
+        status_t deviceClosed(const String8& cameraId);
+
+    private:
+        // create flashlight control based on camera module API and camera
+        // device API versions.
+        status_t createFlashlightControl(const String8& cameraId);
+
+        // mLock should be locked.
+        bool hasFlashUnitLocked(const String8& cameraId);
+
+        sp<FlashControlBase> mFlashControl;
+        CameraModule *mCameraModule;
+        const camera_module_callbacks_t *mCallbacks;
+        SortedVector<String8> mOpenedCameraIds;
+
+        // camera id -> if it has a flash unit
+        KeyedVector<String8, bool> mHasFlashlightMap;
+        bool mFlashlightMapInitialized;
+
+        Mutex mLock; // protect CameraFlashlight API
+};
+
+/**
+ * Flash control for camera module v2.4 and above.
+ */
+class ModuleFlashControl : public FlashControlBase {
+    public:
+        ModuleFlashControl(CameraModule& cameraModule,
+                const camera_module_callbacks_t& callbacks);
+        virtual ~ModuleFlashControl();
+
+        // FlashControlBase
+        status_t hasFlashUnit(const String8& cameraId, bool *hasFlash);
+        status_t setTorchMode(const String8& cameraId, bool enabled);
+
+    private:
+        CameraModule *mCameraModule;
+
+        Mutex mLock;
+};
+
+/**
+ * Flash control for camera module <= v2.3 and camera HAL v2-v3
+ */
+class CameraDeviceClientFlashControl : public FlashControlBase {
+    public:
+        CameraDeviceClientFlashControl(CameraModule& cameraModule,
+                const camera_module_callbacks_t& callbacks);
+        virtual ~CameraDeviceClientFlashControl();
+
+        // FlashControlBase
+        status_t setTorchMode(const String8& cameraId, bool enabled);
+        status_t hasFlashUnit(const String8& cameraId, bool *hasFlash);
+
+    private:
+        // connect to a camera device
+        status_t connectCameraDevice(const String8& cameraId);
+        // disconnect and free mDevice
+        status_t disconnectCameraDevice();
+
+        // initialize a surface
+        status_t initializeSurface(sp<CameraDeviceBase>& device, int32_t width,
+                int32_t height);
+
+        // submit a request to enable the torch mode
+        status_t submitTorchEnabledRequest();
+
+        // get the smallest surface size of IMPLEMENTATION_DEFINED
+        status_t getSmallestSurfaceSize(const camera_info& info, int32_t *width,
+                    int32_t *height);
+
+        // protected by mLock
+        status_t hasFlashUnitLocked(const String8& cameraId, bool *hasFlash);
+
+        CameraModule *mCameraModule;
+        const camera_module_callbacks_t *mCallbacks;
+        String8 mCameraId;
+        bool mTorchEnabled;
+        CameraMetadata *mMetadata;
+        // WORKAROUND: will be set to true for HAL v2 devices where
+        // setStreamingRequest() needs to be call for torch mode settings to
+        // take effect.
+        bool mStreaming;
+
+        sp<CameraDeviceBase> mDevice;
+
+        sp<IGraphicBufferProducer> mProducer;
+        sp<IGraphicBufferConsumer>  mConsumer;
+        sp<GLConsumer> mSurfaceTexture;
+        sp<ANativeWindow> mAnw;
+        int32_t mStreamId;
+
+        Mutex mLock;
+};
+
+/**
+ * Flash control for camera module <= v2.3 and camera HAL v1
+ */
+class CameraHardwareInterfaceFlashControl : public FlashControlBase {
+    public:
+        CameraHardwareInterfaceFlashControl(CameraModule& cameraModule,
+                const camera_module_callbacks_t& callbacks);
+        virtual ~CameraHardwareInterfaceFlashControl();
+
+        // FlashControlBase
+        status_t setTorchMode(const String8& cameraId, bool enabled);
+        status_t hasFlashUnit(const String8& cameraId, bool *hasFlash);
+
+    private:
+        // connect to a camera device
+        status_t connectCameraDevice(const String8& cameraId);
+
+        // disconnect and free mDevice
+        status_t disconnectCameraDevice();
+
+        // initialize the preview window
+        status_t initializePreviewWindow(sp<CameraHardwareInterface> device,
+                int32_t width, int32_t height);
+
+        // start preview and enable torch
+        status_t startPreviewAndTorch();
+
+        // get the smallest surface
+        status_t getSmallestSurfaceSize(int32_t *width, int32_t *height);
+
+        // protected by mLock
+        status_t hasFlashUnitLocked(const String8& cameraId, bool *hasFlash);
+
+        CameraModule *mCameraModule;
+        const camera_module_callbacks_t *mCallbacks;
+        sp<CameraHardwareInterface> mDevice;
+        String8 mCameraId;
+        CameraParameters mParameters;
+        bool mTorchEnabled;
+
+        sp<IGraphicBufferProducer> mProducer;
+        sp<IGraphicBufferConsumer>  mConsumer;
+        sp<GLConsumer> mSurfaceTexture;
+        sp<ANativeWindow> mAnw;
+
+        Mutex mLock;
+};
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index fd5a426..55f7a40 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -17,9 +17,14 @@
 #define LOG_TAG "CameraService"
 //#define LOG_NDEBUG 0
 
+#include <algorithm>
+#include <climits>
 #include <stdio.h>
-#include <string.h>
+#include <cstring>
+#include <ctime>
+#include <string>
 #include <sys/types.h>
+#include <inttypes.h>
 #include <pthread.h>
 
 #include <binder/AppOpsManager.h>
@@ -27,8 +32,10 @@
 #include <binder/IServiceManager.h>
 #include <binder/MemoryBase.h>
 #include <binder/MemoryHeapBase.h>
+#include <binder/ProcessInfoService.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h>
+#include <cutils/multiuser.h>
 #include <gui/Surface.h>
 #include <hardware/hardware.h>
 #include <media/AudioSystem.h>
@@ -66,25 +73,48 @@
 
 // ----------------------------------------------------------------------------
 
-static int getCallingPid() {
-    return IPCThreadState::self()->getCallingPid();
-}
-
-static int getCallingUid() {
-    return IPCThreadState::self()->getCallingUid();
-}
-
 extern "C" {
 static void camera_device_status_change(
         const struct camera_module_callbacks* callbacks,
         int camera_id,
         int new_status) {
     sp<CameraService> cs = const_cast<CameraService*>(
+            static_cast<const CameraService*>(callbacks));
+
+    cs->onDeviceStatusChanged(static_cast<camera_device_status_t>(camera_id),
+            static_cast<camera_device_status_t>(new_status));
+}
+
+static void torch_mode_status_change(
+        const struct camera_module_callbacks* callbacks,
+        const char* camera_id,
+        int new_status) {
+    if (!callbacks || !camera_id) {
+        ALOGE("%s invalid parameters. callbacks %p, camera_id %p", __FUNCTION__,
+                callbacks, camera_id);
+    }
+    sp<CameraService> cs = const_cast<CameraService*>(
                                 static_cast<const CameraService*>(callbacks));
 
-    cs->onDeviceStatusChanged(
-        camera_id,
-        new_status);
+    ICameraServiceListener::TorchStatus status;
+    switch (new_status) {
+        case TORCH_MODE_STATUS_NOT_AVAILABLE:
+            status = ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE;
+            break;
+        case TORCH_MODE_STATUS_AVAILABLE_OFF:
+            status = ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF;
+            break;
+        case TORCH_MODE_STATUS_AVAILABLE_ON:
+            status = ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON;
+            break;
+        default:
+            ALOGE("Unknown torch status %d", new_status);
+            return;
+    }
+
+    cs->onTorchStatusChanged(
+        String8(camera_id),
+        status);
 }
 } // extern "C"
 
@@ -95,49 +125,90 @@
 static CameraService *gCameraService;
 
 CameraService::CameraService()
-    :mSoundRef(0), mModule(0)
+    : mEventLog(DEFAULT_EVICTION_LOG_LENGTH), mSoundRef(0), mModule(0), mFlashlight(0)
 {
     ALOGI("CameraService started (pid=%d)", getpid());
     gCameraService = this;
 
-    for (size_t i = 0; i < MAX_CAMERAS; ++i) {
-        mStatusList[i] = ICameraServiceListener::STATUS_PRESENT;
-    }
-
     this->camera_device_status_change = android::camera_device_status_change;
+    this->torch_mode_status_change = android::torch_mode_status_change;
+
+    mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
 }
 
 void CameraService::onFirstRef()
 {
-    LOG1("CameraService::onFirstRef");
+    ALOGI("CameraService process starting");
 
     BnCameraService::onFirstRef();
 
+    camera_module_t *rawModule;
     if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
-                (const hw_module_t **)&mModule) < 0) {
+                (const hw_module_t **)&rawModule) < 0) {
         ALOGE("Could not load camera HAL module");
         mNumberOfCameras = 0;
     }
     else {
-        ALOGI("Loaded \"%s\" camera module", mModule->common.name);
-        mNumberOfCameras = mModule->get_number_of_cameras();
-        if (mNumberOfCameras > MAX_CAMERAS) {
-            ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
-                    mNumberOfCameras, MAX_CAMERAS);
-            mNumberOfCameras = MAX_CAMERAS;
-        }
-        for (int i = 0; i < mNumberOfCameras; i++) {
-            setCameraFree(i);
+        mModule = new CameraModule(rawModule);
+        const hw_module_t *common = mModule->getRawModule();
+        ALOGI("Loaded \"%s\" camera module", common->name);
+        mNumberOfCameras = mModule->getNumberOfCameras();
+
+        mFlashlight = new CameraFlashlight(*mModule, *this);
+        status_t res = mFlashlight->findFlashUnits();
+        if (res) {
+            // impossible because we haven't open any camera devices.
+            ALOGE("Failed to find flash units.");
         }
 
-        if (mModule->common.module_api_version >=
-                CAMERA_MODULE_API_VERSION_2_1) {
-            mModule->set_callbacks(this);
+        for (int i = 0; i < mNumberOfCameras; i++) {
+            String8 cameraId = String8::format("%d", i);
+
+            // Defaults to use for cost and conflicting devices
+            int cost = 100;
+            char** conflicting_devices = nullptr;
+            size_t conflicting_devices_length = 0;
+
+            // If using post-2.4 module version, query the cost + conflicting devices from the HAL
+            if (common->module_api_version >= CAMERA_MODULE_API_VERSION_2_4) {
+                struct camera_info info;
+                status_t rc = mModule->getCameraInfo(i, &info);
+                if (rc == NO_ERROR) {
+                    cost = info.resource_cost;
+                    conflicting_devices = info.conflicting_devices;
+                    conflicting_devices_length = info.conflicting_devices_length;
+                } else {
+                    ALOGE("%s: Received error loading camera info for device %d, cost and"
+                            " conflicting devices fields set to defaults for this device.",
+                            __FUNCTION__, i);
+                }
+            }
+
+            std::set<String8> conflicting;
+            for (size_t i = 0; i < conflicting_devices_length; i++) {
+                conflicting.emplace(String8(conflicting_devices[i]));
+            }
+
+            // Initialize state for each camera device
+            {
+                Mutex::Autolock lock(mCameraStatesLock);
+                mCameraStates.emplace(cameraId, std::make_shared<CameraState>(cameraId, cost,
+                        conflicting));
+            }
+
+            if (mFlashlight->hasFlashUnit(cameraId)) {
+                mTorchStatusMap.add(cameraId,
+                        ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF);
+            }
+        }
+
+        if (common->module_api_version >= CAMERA_MODULE_API_VERSION_2_1) {
+            mModule->setCallbacks(this);
         }
 
         VendorTagDescriptor::clearGlobalVendorTagDescriptor();
 
-        if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {
+        if (common->module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {
             setUpVendorTags();
         }
 
@@ -146,80 +217,111 @@
 }
 
 CameraService::~CameraService() {
-    for (int i = 0; i < mNumberOfCameras; i++) {
-        if (mBusy[i]) {
-            ALOGE("camera %d is still in use in destructor!", i);
-        }
+    if (mModule) {
+        delete mModule;
+        mModule = nullptr;
     }
-
     VendorTagDescriptor::clearGlobalVendorTagDescriptor();
-    gCameraService = NULL;
+    gCameraService = nullptr;
 }
 
-void CameraService::onDeviceStatusChanged(int cameraId,
-                                          int newStatus)
-{
+void CameraService::onDeviceStatusChanged(camera_device_status_t  cameraId,
+        camera_device_status_t newStatus) {
     ALOGI("%s: Status changed for cameraId=%d, newStatus=%d", __FUNCTION__,
           cameraId, newStatus);
 
-    if (cameraId < 0 || cameraId >= MAX_CAMERAS) {
+    String8 id = String8::format("%d", cameraId);
+    std::shared_ptr<CameraState> state = getCameraState(id);
+
+    if (state == nullptr) {
         ALOGE("%s: Bad camera ID %d", __FUNCTION__, cameraId);
         return;
     }
 
-    if ((int)getStatus(cameraId) == newStatus) {
-        ALOGE("%s: State transition to the same status 0x%x not allowed",
+    ICameraServiceListener::Status oldStatus = state->getStatus();
+
+    if (oldStatus == static_cast<ICameraServiceListener::Status>(newStatus)) {
+        ALOGE("%s: State transition to the same status %#x not allowed", __FUNCTION__, newStatus);
+        return;
+    }
+
+    if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
+        sp<BasicClient> clientToDisconnect;
+        {
+            // Don't do this in updateStatus to avoid deadlock over mServiceLock
+            Mutex::Autolock lock(mServiceLock);
+
+            // Set the device status to NOT_PRESENT, clients will no longer be able to connect
+            // to this device until the status changes
+            updateStatus(ICameraServiceListener::STATUS_NOT_PRESENT, id);
+
+            // Remove cached shim parameters
+            state->setShimParams(CameraParameters());
+
+            // Remove the client from the list of active clients
+            clientToDisconnect = removeClientLocked(id);
+
+            // Notify the client of disconnection
+            clientToDisconnect->notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
+                    CaptureResultExtras{});
+        }
+
+        ALOGI("%s: Client for camera ID %s evicted due to device status change from HAL",
+                __FUNCTION__, id.string());
+
+        // Disconnect client
+        if (clientToDisconnect.get() != nullptr) {
+            // Ensure not in binder RPC so client disconnect PID checks work correctly
+            LOG_ALWAYS_FATAL_IF(getCallingPid() != getpid(),
+                    "onDeviceStatusChanged must be called from the camera service process!");
+            clientToDisconnect->disconnect();
+        }
+
+    } else {
+        updateStatus(static_cast<ICameraServiceListener::Status>(newStatus), id);
+    }
+
+}
+
+void CameraService::onTorchStatusChanged(const String8& cameraId,
+        ICameraServiceListener::TorchStatus newStatus) {
+    Mutex::Autolock al(mTorchStatusMutex);
+    onTorchStatusChangedLocked(cameraId, newStatus);
+}
+
+void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
+        ICameraServiceListener::TorchStatus newStatus) {
+    ALOGI("%s: Torch status changed for cameraId=%s, newStatus=%d",
+            __FUNCTION__, cameraId.string(), newStatus);
+
+    ICameraServiceListener::TorchStatus status;
+    status_t res = getTorchStatusLocked(cameraId, &status);
+    if (res) {
+        ALOGE("%s: cannot get torch status of camera %s", cameraId.string());
+        return;
+    }
+    if (status == newStatus) {
+        ALOGE("%s: Torch state transition to the same status 0x%x not allowed",
               __FUNCTION__, (uint32_t)newStatus);
         return;
     }
 
-    /* don't do this in updateStatus
-       since it is also called from connect and we could get into a deadlock */
-    if (newStatus == CAMERA_DEVICE_STATUS_NOT_PRESENT) {
-        Vector<sp<BasicClient> > clientsToDisconnect;
-        {
-           Mutex::Autolock al(mServiceLock);
-
-           /* Remove cached parameters from shim cache */
-           mShimParams.removeItem(cameraId);
-
-           /* Find all clients that we need to disconnect */
-           sp<BasicClient> client = mClient[cameraId].promote();
-           if (client.get() != NULL) {
-               clientsToDisconnect.push_back(client);
-           }
-
-           int i = cameraId;
-           for (size_t j = 0; j < mProClientList[i].size(); ++j) {
-               sp<ProClient> cl = mProClientList[i][j].promote();
-               if (cl != NULL) {
-                   clientsToDisconnect.push_back(cl);
-               }
-           }
-        }
-
-        /* now disconnect them. don't hold the lock
-           or we can get into a deadlock */
-
-        for (size_t i = 0; i < clientsToDisconnect.size(); ++i) {
-            sp<BasicClient> client = clientsToDisconnect[i];
-
-            client->disconnect();
-            /**
-             * The remote app will no longer be able to call methods on the
-             * client since the client PID will be reset to 0
-             */
-        }
-
-        ALOGV("%s: After unplug, disconnected %zu clients",
-              __FUNCTION__, clientsToDisconnect.size());
+    res = setTorchStatusLocked(cameraId, newStatus);
+    if (res) {
+        ALOGE("%s: Failed to set the torch status", __FUNCTION__,
+                (uint32_t)newStatus);
+        return;
     }
 
-    updateStatus(
-            static_cast<ICameraServiceListener::Status>(newStatus), cameraId);
-
+    {
+        Mutex::Autolock lock(mStatusListenerLock);
+        for (auto& i : mListenerList) {
+            i->onTorchStatusChanged(newStatus, String16{cameraId});
+        }
+    }
 }
 
+
 int32_t CameraService::getNumberOfCameras() {
     return mNumberOfCameras;
 }
@@ -236,12 +338,21 @@
 
     struct camera_info info;
     status_t rc = filterGetInfoErrorCode(
-        mModule->get_camera_info(cameraId, &info));
+        mModule->getCameraInfo(cameraId, &info));
     cameraInfo->facing = info.facing;
     cameraInfo->orientation = info.orientation;
     return rc;
 }
 
+int CameraService::cameraIdToInt(const String8& cameraId) {
+    errno = 0;
+    size_t pos = 0;
+    int ret = stoi(std::string{cameraId.string()}, &pos);
+    if (errno != 0 || pos != cameraId.size()) {
+        return -1;
+    }
+    return ret;
+}
 
 status_t CameraService::generateShimMetadata(int cameraId, /*out*/CameraMetadata* cameraInfo) {
     status_t ret = OK;
@@ -347,7 +458,7 @@
 
     int facing;
     status_t ret = OK;
-    if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_0 ||
+    if (mModule->getRawModule()->module_api_version < CAMERA_MODULE_API_VERSION_2_0 ||
             getDeviceVersion(cameraId, &facing) <= CAMERA_DEVICE_API_VERSION_2_1 ) {
         /**
          * Backwards compatibility mode for old HALs:
@@ -368,13 +479,61 @@
          * Normal HAL 2.1+ codepath.
          */
         struct camera_info info;
-        ret = filterGetInfoErrorCode(mModule->get_camera_info(cameraId, &info));
+        ret = filterGetInfoErrorCode(mModule->getCameraInfo(cameraId, &info));
         *cameraInfo = info.static_camera_characteristics;
     }
 
     return ret;
 }
 
+int CameraService::getCallingPid() {
+    return IPCThreadState::self()->getCallingPid();
+}
+
+int CameraService::getCallingUid() {
+    return IPCThreadState::self()->getCallingUid();
+}
+
+String8 CameraService::getFormattedCurrentTime() {
+    time_t now = time(nullptr);
+    char formattedTime[64];
+    strftime(formattedTime, sizeof(formattedTime), "%m-%d %H:%M:%S", localtime(&now));
+    return String8(formattedTime);
+}
+
+int CameraService::getCameraPriorityFromProcState(int procState) {
+    // Find the priority for the camera usage based on the process state.  Higher priority clients
+    // win for evictions.
+    // Note: Unlike the ordering for ActivityManager, persistent system processes will always lose
+    //       the camera to the top/foreground applications.
+    switch(procState) {
+        case PROCESS_STATE_TOP: // User visible
+            return 100;
+        case PROCESS_STATE_IMPORTANT_FOREGROUND: // Foreground
+            return 90;
+        case PROCESS_STATE_PERSISTENT: // Persistent system services
+        case PROCESS_STATE_PERSISTENT_UI:
+            return 80;
+        case PROCESS_STATE_IMPORTANT_BACKGROUND: // "Important" background processes
+            return 70;
+        case PROCESS_STATE_BACKUP: // Everything else
+        case PROCESS_STATE_HEAVY_WEIGHT:
+        case PROCESS_STATE_SERVICE:
+        case PROCESS_STATE_RECEIVER:
+        case PROCESS_STATE_HOME:
+        case PROCESS_STATE_LAST_ACTIVITY:
+        case PROCESS_STATE_CACHED_ACTIVITY:
+        case PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
+        case PROCESS_STATE_CACHED_EMPTY:
+            return 1;
+        case PROCESS_STATE_NONEXISTENT:
+            return -1;
+        default:
+            ALOGE("%s: Received unknown process state from ActivityManagerService!", __FUNCTION__);
+            return -1;
+    }
+}
+
 status_t CameraService::getCameraVendorTagDescriptor(/*out*/sp<VendorTagDescriptor>& desc) {
     if (!mModule) {
         ALOGE("%s: camera hardware module doesn't exist", __FUNCTION__);
@@ -387,12 +546,12 @@
 
 int CameraService::getDeviceVersion(int cameraId, int* facing) {
     struct camera_info info;
-    if (mModule->get_camera_info(cameraId, &info) != OK) {
+    if (mModule->getCameraInfo(cameraId, &info) != OK) {
         return -1;
     }
 
     int deviceVersion;
-    if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
+    if (mModule->getRawModule()->module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
         deviceVersion = info.device_version;
     } else {
         deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
@@ -405,19 +564,6 @@
     return deviceVersion;
 }
 
-status_t CameraService::filterOpenErrorCode(status_t err) {
-    switch(err) {
-        case NO_ERROR:
-        case -EBUSY:
-        case -EINVAL:
-        case -EUSERS:
-            return err;
-        default:
-            break;
-    }
-    return -ENODEV;
-}
-
 status_t CameraService::filterGetInfoErrorCode(status_t err) {
     switch(err) {
         case NO_ERROR:
@@ -433,13 +579,13 @@
     vendor_tag_ops_t vOps = vendor_tag_ops_t();
 
     // Check if vendor operations have been implemented
-    if (mModule->get_vendor_tag_ops == NULL) {
+    if (!mModule->isVendorTagDefined()) {
         ALOGI("%s: No vendor tags defined for this device.", __FUNCTION__);
         return false;
     }
 
     ATRACE_BEGIN("camera3->get_metadata_vendor_tag_ops");
-    mModule->get_vendor_tag_ops(&vOps);
+    mModule->getVendorTagOps(&vOps);
     ATRACE_END();
 
     // Ensure all vendor operations are present
@@ -467,54 +613,90 @@
     return true;
 }
 
-status_t CameraService::initializeShimMetadata(int cameraId) {
-    int pid = getCallingPid();
-    int uid = getCallingUid();
-    status_t ret = validateConnect(cameraId, uid);
-    if (ret != OK) {
-        // Error already logged by callee
-        return ret;
+status_t CameraService::makeClient(const sp<CameraService>& cameraService,
+        const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
+        int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
+        int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
+        /*out*/sp<BasicClient>* client) {
+
+    // TODO: Update CameraClients + HAL interface to use strings for Camera IDs
+    int id = cameraIdToInt(cameraId);
+    if (id == -1) {
+        ALOGE("%s: Invalid camera ID %s, cannot convert to integer.", __FUNCTION__,
+                cameraId.string());
+        return BAD_VALUE;
     }
 
-    bool needsNewClient = false;
-    sp<Client> client;
+    if (halVersion < 0 || halVersion == deviceVersion) {
+        // Default path: HAL version is unspecified by caller, create CameraClient
+        // based on device version reported by the HAL.
+        switch(deviceVersion) {
+          case CAMERA_DEVICE_API_VERSION_1_0:
+            if (effectiveApiLevel == API_1) {  // Camera1 API route
+                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
+                *client = new CameraClient(cameraService, tmp, packageName, id, facing,
+                        clientPid, clientUid, getpid(), legacyMode);
+            } else { // Camera2 API route
+                ALOGW("Camera using old HAL version: %d", deviceVersion);
+                return -EOPNOTSUPP;
+            }
+            break;
+          case CAMERA_DEVICE_API_VERSION_2_0:
+          case CAMERA_DEVICE_API_VERSION_2_1:
+          case CAMERA_DEVICE_API_VERSION_3_0:
+          case CAMERA_DEVICE_API_VERSION_3_1:
+          case CAMERA_DEVICE_API_VERSION_3_2:
+          case CAMERA_DEVICE_API_VERSION_3_3:
+            if (effectiveApiLevel == API_1) { // Camera1 API route
+                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
+                *client = new Camera2Client(cameraService, tmp, packageName, id, facing,
+                        clientPid, clientUid, servicePid, legacyMode);
+            } else { // Camera2 API route
+                sp<ICameraDeviceCallbacks> tmp =
+                        static_cast<ICameraDeviceCallbacks*>(cameraCb.get());
+                *client = new CameraDeviceClient(cameraService, tmp, packageName, id,
+                        facing, clientPid, clientUid, servicePid);
+            }
+            break;
+          default:
+            // Should not be reachable
+            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
+            return INVALID_OPERATION;
+        }
+    } else {
+        // A particular HAL version is requested by caller. Create CameraClient
+        // based on the requested HAL version.
+        if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
+            halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
+            // Only support higher HAL version device opened as HAL1.0 device.
+            sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
+            *client = new CameraClient(cameraService, tmp, packageName, id, facing,
+                    clientPid, clientUid, servicePid, legacyMode);
+        } else {
+            // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
+            ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
+                    " opened as HAL %x device", halVersion, deviceVersion,
+                    CAMERA_DEVICE_API_VERSION_1_0);
+            return INVALID_OPERATION;
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t CameraService::initializeShimMetadata(int cameraId) {
+    int uid = getCallingUid();
 
     String16 internalPackageName("media");
-    {   // Scope for service lock
-        Mutex::Autolock lock(mServiceLock);
-        if (mClient[cameraId] != NULL) {
-            client = static_cast<Client*>(mClient[cameraId].promote().get());
-        }
-        if (client == NULL) {
-            needsNewClient = true;
-            ret = connectHelperLocked(/*out*/client,
-                                      /*cameraClient*/NULL, // Empty binder callbacks
-                                      cameraId,
-                                      internalPackageName,
-                                      uid,
-                                      pid);
-
-            if (ret != OK) {
-                // Error already logged by callee
-                return ret;
-            }
-        }
-
-        if (client == NULL) {
-            ALOGE("%s: Could not connect to client camera device.", __FUNCTION__);
-            return BAD_VALUE;
-        }
-
-        String8 rawParams = client->getParameters();
-        CameraParameters params(rawParams);
-        mShimParams.add(cameraId, params);
+    String8 id = String8::format("%d", cameraId);
+    status_t ret = NO_ERROR;
+    sp<Client> tmp = nullptr;
+    if ((ret = connectHelper<ICameraClient,Client>(sp<ICameraClient>{nullptr}, id,
+            static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED), internalPackageName, uid, API_1,
+            false, true, tmp)) != NO_ERROR) {
+        ALOGE("%s: Error %d (%s) initializing shim metadata.", __FUNCTION__, ret, strerror(ret));
+        return ret;
     }
-
-    // Close client if one was opened solely for this call
-    if (needsNewClient) {
-        client->disconnect();
-    }
-    return OK;
+    return NO_ERROR;
 }
 
 status_t CameraService::getLegacyParametersLazy(int cameraId,
@@ -530,42 +712,54 @@
         return BAD_VALUE;
     }
 
-    ssize_t index = -1;
-    {   // Scope for service lock
+    String8 id = String8::format("%d", cameraId);
+
+    // Check if we already have parameters
+    {
+        // Scope for service lock
         Mutex::Autolock lock(mServiceLock);
-        index = mShimParams.indexOfKey(cameraId);
-        // Release service lock so initializeShimMetadata can be called correctly.
-
-        if (index >= 0) {
-            *parameters = mShimParams[index];
+        auto cameraState = getCameraState(id);
+        if (cameraState == nullptr) {
+            ALOGE("%s: Invalid camera ID: %s", __FUNCTION__, id.string());
+            return BAD_VALUE;
+        }
+        CameraParameters p = cameraState->getShimParams();
+        if (!p.isEmpty()) {
+            *parameters = p;
+            return NO_ERROR;
         }
     }
 
-    if (index < 0) {
-        int64_t token = IPCThreadState::self()->clearCallingIdentity();
-        ret = initializeShimMetadata(cameraId);
-        IPCThreadState::self()->restoreCallingIdentity(token);
-        if (ret != OK) {
-            // Error already logged by callee
-            return ret;
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    ret = initializeShimMetadata(cameraId);
+    IPCThreadState::self()->restoreCallingIdentity(token);
+    if (ret != NO_ERROR) {
+        // Error already logged by callee
+        return ret;
+    }
+
+    // Check for parameters again
+    {
+        // Scope for service lock
+        Mutex::Autolock lock(mServiceLock);
+        auto cameraState = getCameraState(id);
+        if (cameraState == nullptr) {
+            ALOGE("%s: Invalid camera ID: %s", __FUNCTION__, id.string());
+            return BAD_VALUE;
         }
-
-        {   // Scope for service lock
-            Mutex::Autolock lock(mServiceLock);
-            index = mShimParams.indexOfKey(cameraId);
-
-            LOG_ALWAYS_FATAL_IF(index < 0, "index should have been initialized");
-
-            *parameters = mShimParams[index];
+        CameraParameters p = cameraState->getShimParams();
+        if (!p.isEmpty()) {
+            *parameters = p;
+            return NO_ERROR;
         }
     }
 
-    return OK;
+    ALOGE("%s: Parameters were not initialized, or were empty.  Device may not be present.",
+            __FUNCTION__);
+    return INVALID_OPERATION;
 }
 
-status_t CameraService::validateConnect(int cameraId,
-                                    /*inout*/
-                                    int& clientUid) const {
+status_t CameraService::validateConnect(const String8& cameraId, /*inout*/int& clientUid) const {
 
     int callingPid = getCallingPid();
 
@@ -574,160 +768,244 @@
     } else {
         // We only trust our own process to forward client UIDs
         if (callingPid != getpid()) {
-            ALOGE("CameraService::connect X (pid %d) rejected (don't trust clientUid)",
+            ALOGE("CameraService::connect X (PID %d) rejected (don't trust clientUid)",
                     callingPid);
             return PERMISSION_DENIED;
         }
     }
 
     if (!mModule) {
-        ALOGE("Camera HAL module not loaded");
+        ALOGE("CameraService::connect X (PID %d) rejected (camera HAL module not loaded)",
+                callingPid);
         return -ENODEV;
     }
 
-    if (cameraId < 0 || cameraId >= mNumberOfCameras) {
-        ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
-            callingPid, cameraId);
+    if (getCameraState(cameraId) == nullptr) {
+        ALOGE("CameraService::connect X (PID %d) rejected (invalid camera ID %s)", callingPid,
+                cameraId.string());
         return -ENODEV;
     }
 
+    // Check device policy for this camera
     char value[PROPERTY_VALUE_MAX];
-    property_get("sys.secpolicy.camera.disabled", value, "0");
+    char key[PROPERTY_KEY_MAX];
+    int clientUserId = multiuser_get_user_id(clientUid);
+    snprintf(key, PROPERTY_KEY_MAX, "sys.secpolicy.camera.off_%d", clientUserId);
+    property_get(key, value, "0");
     if (strcmp(value, "1") == 0) {
         // Camera is disabled by DevicePolicyManager.
-        ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
+        ALOGE("CameraService::connect X (PID %d) rejected (camera %s is disabled by device "
+                "policy)", callingPid, cameraId.string());
         return -EACCES;
     }
 
-    ICameraServiceListener::Status currentStatus = getStatus(cameraId);
+    return checkIfDeviceIsUsable(cameraId);
+}
+
+status_t CameraService::checkIfDeviceIsUsable(const String8& cameraId) const {
+    auto cameraState = getCameraState(cameraId);
+    int callingPid = getCallingPid();
+    if (cameraState == nullptr) {
+        ALOGE("CameraService::connect X (PID %d) rejected (invalid camera ID %s)", callingPid,
+                cameraId.string());
+        return -ENODEV;
+    }
+
+    ICameraServiceListener::Status currentStatus = cameraState->getStatus();
     if (currentStatus == ICameraServiceListener::STATUS_NOT_PRESENT) {
-        ALOGI("Camera is not plugged in,"
-               " connect X (pid %d) rejected", callingPid);
+        ALOGE("CameraService::connect X (PID %d) rejected (camera %s is not connected)",
+                callingPid, cameraId.string());
         return -ENODEV;
     } else if (currentStatus == ICameraServiceListener::STATUS_ENUMERATING) {
-        ALOGI("Camera is enumerating,"
-               " connect X (pid %d) rejected", callingPid);
+        ALOGE("CameraService::connect X (PID %d) rejected, (camera %s is initializing)",
+                callingPid, cameraId.string());
         return -EBUSY;
     }
-    // Else don't check for STATUS_NOT_AVAILABLE.
-    //  -- It's done implicitly in canConnectUnsafe /w the mBusy array
 
-    return OK;
+    return NO_ERROR;
 }
 
-bool CameraService::canConnectUnsafe(int cameraId,
-                                     const String16& clientPackageName,
-                                     const sp<IBinder>& remoteCallback,
-                                     sp<BasicClient> &client) {
-    String8 clientName8(clientPackageName);
-    int callingPid = getCallingPid();
+void CameraService::finishConnectLocked(const sp<BasicClient>& client,
+        const CameraService::DescriptorPtr& desc) {
 
-    if (mClient[cameraId] != 0) {
-        client = mClient[cameraId].promote();
-        if (client != 0) {
-            if (remoteCallback == client->getRemote()) {
-                LOG1("CameraService::connect X (pid %d) (the same client)",
-                     callingPid);
-                return true;
-            } else {
-                // TODOSC: need to support 1 regular client,
-                // multiple shared clients here
-                ALOGW("CameraService::connect X (pid %d) rejected"
-                      " (existing client).", callingPid);
-                return false;
+    // Make a descriptor for the incoming client
+    auto clientDescriptor = CameraService::CameraClientManager::makeClientDescriptor(client, desc);
+    auto evicted = mActiveClientManager.addAndEvict(clientDescriptor);
+
+    logConnected(desc->getKey(), static_cast<int>(desc->getOwnerId()),
+            String8(client->getPackageName()));
+
+    if (evicted.size() > 0) {
+        // This should never happen - clients should already have been removed in disconnect
+        for (auto& i : evicted) {
+            ALOGE("%s: Invalid state: Client for camera %s was not removed in disconnect",
+                    __FUNCTION__, i->getKey().string());
+        }
+
+        LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, clients not evicted properly",
+                __FUNCTION__);
+    }
+}
+
+status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clientPid,
+        apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,
+        /*out*/
+        sp<BasicClient>* client,
+        std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial) {
+
+    status_t ret = NO_ERROR;
+    std::vector<sp<BasicClient>> evictedClients;
+    DescriptorPtr clientDescriptor;
+    {
+        if (effectiveApiLevel == API_1) {
+            // If we are using API1, any existing client for this camera ID with the same remote
+            // should be returned rather than evicted to allow MediaRecorder to work properly.
+
+            auto current = mActiveClientManager.get(cameraId);
+            if (current != nullptr) {
+                auto clientSp = current->getValue();
+                if (clientSp.get() != nullptr) { // should never be needed
+                    if (clientSp->getRemote() == remoteCallback) {
+                        ALOGI("CameraService::connect X (PID %d) (second call from same"
+                                "app binder, returning the same client)", clientPid);
+                        *client = clientSp;
+                        return NO_ERROR;
+                    }
+                }
             }
         }
-        mClient[cameraId].clear();
-    }
 
-    /*
-    mBusy is set to false as the last step of the Client destructor,
-    after which it is guaranteed that the Client destructor has finished (
-    including any inherited destructors)
+        // Return error if the device was unplugged or removed by the HAL for some reason
+        if ((ret = checkIfDeviceIsUsable(cameraId)) != NO_ERROR) {
+            return ret;
+        }
 
-    We only need this for a Client subclasses since we don't allow
-    multiple Clents to be opened concurrently, but multiple BasicClient
-    would be fine
-    */
-    if (mBusy[cameraId]) {
-        ALOGW("CameraService::connect X (pid %d, \"%s\") rejected"
-                " (camera %d is still busy).", callingPid,
-                clientName8.string(), cameraId);
-        return false;
-    }
+        // Get current active client PIDs
+        std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
+        ownerPids.push_back(clientPid);
 
-    return true;
-}
+        // Use the value +PROCESS_STATE_NONEXISTENT, to avoid taking
+        // address of PROCESS_STATE_NONEXISTENT as a reference argument
+        // for the vector constructor. PROCESS_STATE_NONEXISTENT does
+        // not have an out-of-class definition.
+        std::vector<int> priorities(ownerPids.size(), +PROCESS_STATE_NONEXISTENT);
 
-status_t CameraService::connectHelperLocked(
-        /*out*/
-        sp<Client>& client,
-        /*in*/
-        const sp<ICameraClient>& cameraClient,
-        int cameraId,
-        const String16& clientPackageName,
-        int clientUid,
-        int callingPid,
-        int halVersion,
-        bool legacyMode) {
+        // Get priorites of all active PIDs
+        ProcessInfoService::getProcessStatesFromPids(ownerPids.size(), &ownerPids[0],
+                /*out*/&priorities[0]);
 
-    int facing = -1;
-    int deviceVersion = getDeviceVersion(cameraId, &facing);
+        // Update all active clients' priorities
+        std::map<int,int> pidToPriorityMap;
+        for (size_t i = 0; i < ownerPids.size() - 1; i++) {
+            pidToPriorityMap.emplace(ownerPids[i], getCameraPriorityFromProcState(priorities[i]));
+        }
+        mActiveClientManager.updatePriorities(pidToPriorityMap);
 
-    if (halVersion < 0 || halVersion == deviceVersion) {
-        // Default path: HAL version is unspecified by caller, create CameraClient
-        // based on device version reported by the HAL.
-        switch(deviceVersion) {
-          case CAMERA_DEVICE_API_VERSION_1_0:
-            client = new CameraClient(this, cameraClient,
-                    clientPackageName, cameraId,
-                    facing, callingPid, clientUid, getpid(), legacyMode);
-            break;
-          case CAMERA_DEVICE_API_VERSION_2_0:
-          case CAMERA_DEVICE_API_VERSION_2_1:
-          case CAMERA_DEVICE_API_VERSION_3_0:
-          case CAMERA_DEVICE_API_VERSION_3_1:
-          case CAMERA_DEVICE_API_VERSION_3_2:
-            client = new Camera2Client(this, cameraClient,
-                    clientPackageName, cameraId,
-                    facing, callingPid, clientUid, getpid(), legacyMode);
-            break;
-          case -1:
-            ALOGE("Invalid camera id %d", cameraId);
+        // Get state for the given cameraId
+        auto state = getCameraState(cameraId);
+        if (state == nullptr) {
+            ALOGE("CameraService::connect X (PID %d) rejected (no camera device with ID %s)",
+                clientPid, cameraId.string());
             return BAD_VALUE;
-          default:
-            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
-            return INVALID_OPERATION;
         }
-    } else {
-        // A particular HAL version is requested by caller. Create CameraClient
-        // based on the requested HAL version.
-        if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
-            halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
-            // Only support higher HAL version device opened as HAL1.0 device.
-            client = new CameraClient(this, cameraClient,
-                    clientPackageName, cameraId,
-                    facing, callingPid, clientUid, getpid(), legacyMode);
-        } else {
-            // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
-            ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
-                    " opened as HAL %x device", halVersion, deviceVersion,
-                    CAMERA_DEVICE_API_VERSION_1_0);
-            return INVALID_OPERATION;
+
+        // Make descriptor for incoming client
+        clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
+                sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
+                state->getConflicting(),
+                getCameraPriorityFromProcState(priorities[priorities.size() - 1]), clientPid);
+
+        // Find clients that would be evicted
+        auto evicted = mActiveClientManager.wouldEvict(clientDescriptor);
+
+        // If the incoming client was 'evicted,' higher priority clients have the camera in the
+        // background, so we cannot do evictions
+        if (std::find(evicted.begin(), evicted.end(), clientDescriptor) != evicted.end()) {
+            ALOGE("CameraService::connect X (PID %d) rejected (existing client(s) with higher"
+                    " priority).", clientPid);
+
+            sp<BasicClient> clientSp = clientDescriptor->getValue();
+            String8 curTime = getFormattedCurrentTime();
+            auto incompatibleClients =
+                    mActiveClientManager.getIncompatibleClients(clientDescriptor);
+
+            String8 msg = String8::format("%s : DENIED connect device %s client for package %s "
+                    "(PID %d, priority %d)", curTime.string(),
+                    cameraId.string(), packageName.string(), clientPid,
+                    getCameraPriorityFromProcState(priorities[priorities.size() - 1]));
+
+            for (auto& i : incompatibleClients) {
+                msg.appendFormat("\n   - Blocked by existing device %s client for package %s"
+                        "(PID %" PRId32 ", priority %" PRId32 ")", i->getKey().string(),
+                        String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),
+                        i->getPriority());
+            }
+
+            // Log the client's attempt
+            mEventLog.add(msg);
+
+            return -EBUSY;
+        }
+
+        for (auto& i : evicted) {
+            sp<BasicClient> clientSp = i->getValue();
+            if (clientSp.get() == nullptr) {
+                ALOGE("%s: Invalid state: Null client in active client list.", __FUNCTION__);
+
+                // TODO: Remove this
+                LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, null client in active list",
+                        __FUNCTION__);
+                mActiveClientManager.remove(i);
+                continue;
+            }
+
+            ALOGE("CameraService::connect evicting conflicting client for camera ID %s",
+                    i->getKey().string());
+            evictedClients.push_back(clientSp);
+
+            String8 curTime = getFormattedCurrentTime();
+
+            // Log the clients evicted
+            mEventLog.add(String8::format("%s : EVICT device %s client for package %s (PID %"
+                    PRId32 ", priority %" PRId32 ")\n   - Evicted by device %s client for "
+                    "package %s (PID %d, priority %" PRId32 ")", curTime.string(),
+                    i->getKey().string(), String8{clientSp->getPackageName()}.string(),
+                    i->getOwnerId(), i->getPriority(), cameraId.string(),
+                    packageName.string(), clientPid,
+                    getCameraPriorityFromProcState(priorities[priorities.size() - 1])));
+
+            // Notify the client of disconnection
+            clientSp->notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
+                    CaptureResultExtras());
         }
     }
 
-    status_t status = connectFinishUnsafe(client, client->getRemote());
-    if (status != OK) {
-        // this is probably not recoverable.. maybe the client can try again
-        return status;
+    // Do not hold mServiceLock while disconnecting clients, but retain the condition blocking
+    // other clients from connecting in mServiceLockWrapper if held
+    mServiceLock.unlock();
+
+    // Clear caller identity temporarily so client disconnect PID checks work correctly
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+
+    // Destroy evicted clients
+    for (auto& i : evictedClients) {
+        // Disconnect is blocking, and should only have returned when HAL has cleaned up
+        i->disconnect(); // Clients will remove themselves from the active client list here
+    }
+    evictedClients.clear();
+
+    IPCThreadState::self()->restoreCallingIdentity(token);
+
+    // Once clients have been disconnected, relock
+    mServiceLock.lock();
+
+    // Check again if the device was unplugged or something while we weren't holding mServiceLock
+    if ((ret = checkIfDeviceIsUsable(cameraId)) != NO_ERROR) {
+        return ret;
     }
 
-    mClient[cameraId] = client;
-    LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId,
-         getpid());
-
-    return OK;
+    *partial = clientDescriptor;
+    return NO_ERROR;
 }
 
 status_t CameraService::connect(
@@ -738,47 +1016,18 @@
         /*out*/
         sp<ICamera>& device) {
 
-    String8 clientName8(clientPackageName);
-    int callingPid = getCallingPid();
+    status_t ret = NO_ERROR;
+    String8 id = String8::format("%d", cameraId);
+    sp<Client> client = nullptr;
+    ret = connectHelper<ICameraClient,Client>(cameraClient, id, CAMERA_HAL_API_VERSION_UNSPECIFIED,
+            clientPackageName, clientUid, API_1, false, false, /*out*/client);
 
-    LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
-            clientName8.string(), cameraId);
-
-    status_t status = validateConnect(cameraId, /*inout*/clientUid);
-    if (status != OK) {
-        return status;
+    if(ret != NO_ERROR) {
+        return ret;
     }
 
-
-    sp<Client> client;
-    {
-        Mutex::Autolock lock(mServiceLock);
-        sp<BasicClient> clientTmp;
-        if (!canConnectUnsafe(cameraId, clientPackageName,
-                              cameraClient->asBinder(),
-                              /*out*/clientTmp)) {
-            return -EBUSY;
-        } else if (client.get() != NULL) {
-            device = static_cast<Client*>(clientTmp.get());
-            return OK;
-        }
-
-        status = connectHelperLocked(/*out*/client,
-                                     cameraClient,
-                                     cameraId,
-                                     clientPackageName,
-                                     clientUid,
-                                     callingPid);
-        if (status != OK) {
-            return status;
-        }
-
-    }
-    // important: release the mutex here so the client can call back
-    //    into the service from its destructor (can be at the end of the call)
-
     device = client;
-    return OK;
+    return NO_ERROR;
 }
 
 status_t CameraService::connectLegacy(
@@ -789,8 +1038,9 @@
         /*out*/
         sp<ICamera>& device) {
 
+    int apiVersion = mModule->getRawModule()->module_api_version;
     if (halVersion != CAMERA_HAL_API_VERSION_UNSPECIFIED &&
-            mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_3) {
+            apiVersion < CAMERA_MODULE_API_VERSION_2_3) {
         /*
          * Either the HAL version is unspecified in which case this just creates
          * a camera client selected by the latest device version, or
@@ -798,141 +1048,32 @@
          * the open_legacy call
          */
         ALOGE("%s: camera HAL module version %x doesn't support connecting to legacy HAL devices!",
-                __FUNCTION__, mModule->common.module_api_version);
+                __FUNCTION__, apiVersion);
         return INVALID_OPERATION;
     }
 
-    String8 clientName8(clientPackageName);
-    int callingPid = getCallingPid();
+    status_t ret = NO_ERROR;
+    String8 id = String8::format("%d", cameraId);
+    sp<Client> client = nullptr;
+    ret = connectHelper<ICameraClient,Client>(cameraClient, id, halVersion, clientPackageName,
+            clientUid, API_1, true, false, /*out*/client);
 
-    LOG1("CameraService::connect legacy E (pid %d \"%s\", id %d)", callingPid,
-            clientName8.string(), cameraId);
-
-    status_t status = validateConnect(cameraId, /*inout*/clientUid);
-    if (status != OK) {
-        return status;
+    if(ret != NO_ERROR) {
+        return ret;
     }
 
-    sp<Client> client;
-    {
-        Mutex::Autolock lock(mServiceLock);
-        sp<BasicClient> clientTmp;
-        if (!canConnectUnsafe(cameraId, clientPackageName,
-                              cameraClient->asBinder(),
-                              /*out*/clientTmp)) {
-            return -EBUSY;
-        } else if (client.get() != NULL) {
-            device = static_cast<Client*>(clientTmp.get());
-            return OK;
-        }
-
-        status = connectHelperLocked(/*out*/client,
-                                     cameraClient,
-                                     cameraId,
-                                     clientPackageName,
-                                     clientUid,
-                                     callingPid,
-                                     halVersion,
-                                     /*legacyMode*/true);
-        if (status != OK) {
-            return status;
-        }
-
-    }
-    // important: release the mutex here so the client can call back
-    //    into the service from its destructor (can be at the end of the call)
-
     device = client;
-    return OK;
+    return NO_ERROR;
 }
 
-status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client,
-                                            const sp<IBinder>& remoteCallback) {
-    status_t status = client->initialize(mModule);
-    if (status != OK) {
-        return status;
-    }
-    if (remoteCallback != NULL) {
-        remoteCallback->linkToDeath(this);
-    }
-
-    return OK;
-}
-
-status_t CameraService::connectPro(
-                                        const sp<IProCameraCallbacks>& cameraCb,
-                                        int cameraId,
-                                        const String16& clientPackageName,
-                                        int clientUid,
-                                        /*out*/
-                                        sp<IProCameraUser>& device)
-{
-    if (cameraCb == 0) {
-        ALOGE("%s: Callback must not be null", __FUNCTION__);
-        return BAD_VALUE;
-    }
-
-    String8 clientName8(clientPackageName);
-    int callingPid = getCallingPid();
-
-    LOG1("CameraService::connectPro E (pid %d \"%s\", id %d)", callingPid,
-            clientName8.string(), cameraId);
-    status_t status = validateConnect(cameraId, /*inout*/clientUid);
-    if (status != OK) {
-        return status;
-    }
-
-    sp<ProClient> client;
-    {
-        Mutex::Autolock lock(mServiceLock);
-        {
-            sp<BasicClient> client;
-            if (!canConnectUnsafe(cameraId, clientPackageName,
-                                  cameraCb->asBinder(),
-                                  /*out*/client)) {
-                return -EBUSY;
-            }
-        }
-
-        int facing = -1;
-        int deviceVersion = getDeviceVersion(cameraId, &facing);
-
-        switch(deviceVersion) {
-          case CAMERA_DEVICE_API_VERSION_1_0:
-            ALOGE("Camera id %d uses HALv1, doesn't support ProCamera",
-                  cameraId);
-            return -EOPNOTSUPP;
-            break;
-          case CAMERA_DEVICE_API_VERSION_2_0:
-          case CAMERA_DEVICE_API_VERSION_2_1:
-          case CAMERA_DEVICE_API_VERSION_3_0:
-          case CAMERA_DEVICE_API_VERSION_3_1:
-          case CAMERA_DEVICE_API_VERSION_3_2:
-            client = new ProCamera2Client(this, cameraCb, clientPackageName,
-                    cameraId, facing, callingPid, clientUid, getpid());
-            break;
-          case -1:
-            ALOGE("Invalid camera id %d", cameraId);
-            return BAD_VALUE;
-          default:
-            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
-            return INVALID_OPERATION;
-        }
-
-        status_t status = connectFinishUnsafe(client, client->getRemote());
-        if (status != OK) {
-            return status;
-        }
-
-        mProClientList[cameraId].push(client);
-
-        LOG1("CameraService::connectPro X (id %d, this pid is %d)", cameraId,
-                getpid());
-    }
-    // important: release the mutex here so the client can call back
-    //    into the service from its destructor (can be at the end of the call)
-    device = client;
-    return OK;
+status_t CameraService::connectPro(const sp<IProCameraCallbacks>& cameraCb,
+                                   int cameraId,
+                                   const String16& clientPackageName,
+                                   int clientUid,
+                                   /*out*/
+                                   sp<IProCameraUser>& device) {
+    ALOGE("%s: Unimplemented, please use connectDevice", __FUNCTION__);
+    return INVALID_OPERATION;
 }
 
 status_t CameraService::connectDevice(
@@ -941,74 +1082,98 @@
         const String16& clientPackageName,
         int clientUid,
         /*out*/
-        sp<ICameraDeviceUser>& device)
-{
+        sp<ICameraDeviceUser>& device) {
 
-    String8 clientName8(clientPackageName);
-    int callingPid = getCallingPid();
+    status_t ret = NO_ERROR;
+    String8 id = String8::format("%d", cameraId);
+    sp<CameraDeviceClient> client = nullptr;
+    ret = connectHelper<ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
+            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, API_2, false, false,
+            /*out*/client);
 
-    LOG1("CameraService::connectDevice E (pid %d \"%s\", id %d)", callingPid,
-            clientName8.string(), cameraId);
-
-    status_t status = validateConnect(cameraId, /*inout*/clientUid);
-    if (status != OK) {
-        return status;
+    if(ret != NO_ERROR) {
+        return ret;
     }
 
-    sp<CameraDeviceClient> client;
-    {
-        Mutex::Autolock lock(mServiceLock);
-        {
-            sp<BasicClient> client;
-            if (!canConnectUnsafe(cameraId, clientPackageName,
-                                  cameraCb->asBinder(),
-                                  /*out*/client)) {
-                return -EBUSY;
-            }
-        }
-
-        int facing = -1;
-        int deviceVersion = getDeviceVersion(cameraId, &facing);
-
-        switch(deviceVersion) {
-          case CAMERA_DEVICE_API_VERSION_1_0:
-            ALOGW("Camera using old HAL version: %d", deviceVersion);
-            return -EOPNOTSUPP;
-           // TODO: don't allow 2.0  Only allow 2.1 and higher
-          case CAMERA_DEVICE_API_VERSION_2_0:
-          case CAMERA_DEVICE_API_VERSION_2_1:
-          case CAMERA_DEVICE_API_VERSION_3_0:
-          case CAMERA_DEVICE_API_VERSION_3_1:
-          case CAMERA_DEVICE_API_VERSION_3_2:
-            client = new CameraDeviceClient(this, cameraCb, clientPackageName,
-                    cameraId, facing, callingPid, clientUid, getpid());
-            break;
-          case -1:
-            ALOGE("Invalid camera id %d", cameraId);
-            return BAD_VALUE;
-          default:
-            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
-            return INVALID_OPERATION;
-        }
-
-        status_t status = connectFinishUnsafe(client, client->getRemote());
-        if (status != OK) {
-            // this is probably not recoverable.. maybe the client can try again
-            return status;
-        }
-
-        LOG1("CameraService::connectDevice X (id %d, this pid is %d)", cameraId,
-                getpid());
-
-        mClient[cameraId] = client;
-    }
-    // important: release the mutex here so the client can call back
-    //    into the service from its destructor (can be at the end of the call)
-
     device = client;
-    return OK;
+    return NO_ERROR;
 }
 
+status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,
+        const sp<IBinder>& clientBinder) {
+    if (enabled && clientBinder == NULL) {
+        ALOGE("%s: torch client binder is NULL", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    String8 id = String8(cameraId.string());
+
+    // verify id is valid.
+    auto state = getCameraState(id);
+    if (state == nullptr) {
+        ALOGE("%s: camera id is invalid %s", id.string());
+        return -EINVAL;
+    }
+
+    ICameraServiceListener::Status cameraStatus = state->getStatus();
+    if (cameraStatus != ICameraServiceListener::STATUS_PRESENT &&
+            cameraStatus != ICameraServiceListener::STATUS_NOT_AVAILABLE) {
+        ALOGE("%s: camera id is invalid %s", id.string());
+        return -EINVAL;
+    }
+
+    {
+        Mutex::Autolock al(mTorchStatusMutex);
+        ICameraServiceListener::TorchStatus status;
+        status_t res = getTorchStatusLocked(id, &status);
+        if (res) {
+            ALOGE("%s: getting current torch status failed for camera %s",
+                    __FUNCTION__, id.string());
+            return -EINVAL;
+        }
+
+        if (status == ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE) {
+            if (cameraStatus == ICameraServiceListener::STATUS_NOT_AVAILABLE) {
+                ALOGE("%s: torch mode of camera %s is not available because "
+                        "camera is in use", __FUNCTION__, id.string());
+                return -EBUSY;
+            } else {
+                ALOGE("%s: torch mode of camera %s is not available due to "
+                        "insufficient resources", __FUNCTION__, id.string());
+                return -EUSERS;
+            }
+        }
+    }
+
+    status_t res = mFlashlight->setTorchMode(id, enabled);
+    if (res) {
+        ALOGE("%s: setting torch mode of camera %s to %d failed. %s (%d)",
+                __FUNCTION__, id.string(), enabled, strerror(-res), res);
+        return res;
+    }
+
+    {
+        // update the link to client's death
+        Mutex::Autolock al(mTorchClientMapMutex);
+        ssize_t index = mTorchClientMap.indexOfKey(id);
+        if (enabled) {
+            if (index == NAME_NOT_FOUND) {
+                mTorchClientMap.add(id, clientBinder);
+            } else {
+                const sp<IBinder> oldBinder = mTorchClientMap.valueAt(index);
+                oldBinder->unlinkToDeath(this);
+
+                mTorchClientMap.replaceValueAt(index, clientBinder);
+            }
+            clientBinder->linkToDeath(this);
+        } else if (index != NAME_NOT_FOUND) {
+            sp<IBinder> oldBinder = mTorchClientMap.valueAt(index);
+            oldBinder->unlinkToDeath(this);
+        }
+    }
+
+    return OK;
+}
 
 status_t CameraService::addListener(
                                 const sp<ICameraServiceListener>& listener) {
@@ -1021,30 +1186,45 @@
 
     Mutex::Autolock lock(mServiceLock);
 
-    Vector<sp<ICameraServiceListener> >::iterator it, end;
-    for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
-        if ((*it)->asBinder() == listener->asBinder()) {
-            ALOGW("%s: Tried to add listener %p which was already subscribed",
-                  __FUNCTION__, listener.get());
-            return ALREADY_EXISTS;
+    {
+        Mutex::Autolock lock(mStatusListenerLock);
+        for (auto& it : mListenerList) {
+            if (IInterface::asBinder(it) == IInterface::asBinder(listener)) {
+                ALOGW("%s: Tried to add listener %p which was already subscribed",
+                      __FUNCTION__, listener.get());
+                return ALREADY_EXISTS;
+            }
         }
+
+        mListenerList.push_back(listener);
     }
 
-    mListenerList.push_back(listener);
 
     /* Immediately signal current status to this listener only */
     {
-        Mutex::Autolock m(mStatusMutex) ;
-        int numCams = getNumberOfCameras();
-        for (int i = 0; i < numCams; ++i) {
-            listener->onStatusChanged(mStatusList[i], i);
+        Mutex::Autolock lock(mCameraStatesLock);
+        for (auto& i : mCameraStates) {
+            // TODO: Update binder to use String16 for camera IDs and remove;
+            int id = cameraIdToInt(i.first);
+            if (id == -1) continue;
+
+            listener->onStatusChanged(i.second->getStatus(), id);
+        }
+    }
+
+    /* Immediately signal current torch status to this listener only */
+    {
+        Mutex::Autolock al(mTorchStatusMutex);
+        for (size_t i = 0; i < mTorchStatusMap.size(); i++ ) {
+            String16 id = String16(mTorchStatusMap.keyAt(i).string());
+            listener->onTorchStatusChanged(mTorchStatusMap.valueAt(i), id);
         }
     }
 
     return OK;
 }
-status_t CameraService::removeListener(
-                                const sp<ICameraServiceListener>& listener) {
+
+status_t CameraService::removeListener(const sp<ICameraServiceListener>& listener) {
     ALOGV("%s: Remove listener %p", __FUNCTION__, listener.get());
 
     if (listener == 0) {
@@ -1054,11 +1234,13 @@
 
     Mutex::Autolock lock(mServiceLock);
 
-    Vector<sp<ICameraServiceListener> >::iterator it;
-    for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
-        if ((*it)->asBinder() == listener->asBinder()) {
-            mListenerList.erase(it);
-            return OK;
+    {
+        Mutex::Autolock lock(mStatusListenerLock);
+        for (auto it = mListenerList.begin(); it != mListenerList.end(); it++) {
+            if (IInterface::asBinder(*it) == IInterface::asBinder(listener)) {
+                mListenerList.erase(it);
+                return OK;
+            }
         }
     }
 
@@ -1068,10 +1250,7 @@
     return BAD_VALUE;
 }
 
-status_t CameraService::getLegacyParameters(
-            int cameraId,
-            /*out*/
-            String16* parameters) {
+status_t CameraService::getLegacyParameters(int cameraId, /*out*/String16* parameters) {
     ALOGV("%s: for camera ID = %d", __FUNCTION__, cameraId);
 
     if (parameters == NULL) {
@@ -1126,6 +1305,7 @@
             return OK;
         }
       case CAMERA_DEVICE_API_VERSION_3_2:
+      case CAMERA_DEVICE_API_VERSION_3_3:
         ALOGV("%s: Camera id %d uses HAL3.2 or newer, supports api1/api2 directly",
                 __FUNCTION__, cameraId);
         return OK;
@@ -1140,127 +1320,107 @@
     return OK;
 }
 
-void CameraService::removeClientByRemote(const wp<IBinder>& remoteBinder) {
-    int callingPid = getCallingPid();
-    LOG1("CameraService::removeClientByRemote E (pid %d)", callingPid);
-
-    // Declare this before the lock to make absolutely sure the
-    // destructor won't be called with the lock held.
+void CameraService::removeByClient(const BasicClient* client) {
     Mutex::Autolock lock(mServiceLock);
-
-    int outIndex;
-    sp<BasicClient> client = findClientUnsafe(remoteBinder, outIndex);
-
-    if (client != 0) {
-        // Found our camera, clear and leave.
-        LOG1("removeClient: clear camera %d", outIndex);
-
-        sp<IBinder> remote = client->getRemote();
-        if (remote != NULL) {
-            remote->unlinkToDeath(this);
-        }
-
-        mClient[outIndex].clear();
-    } else {
-
-        sp<ProClient> clientPro = findProClientUnsafe(remoteBinder);
-
-        if (clientPro != NULL) {
-            // Found our camera, clear and leave.
-            LOG1("removeClient: clear pro %p", clientPro.get());
-
-            clientPro->getRemoteCallback()->asBinder()->unlinkToDeath(this);
+    for (auto& i : mActiveClientManager.getAll()) {
+        auto clientSp = i->getValue();
+        if (clientSp.get() == client) {
+            mActiveClientManager.remove(i);
         }
     }
-
-    LOG1("CameraService::removeClientByRemote X (pid %d)", callingPid);
 }
 
-sp<CameraService::ProClient> CameraService::findProClientUnsafe(
-                        const wp<IBinder>& cameraCallbacksRemote)
-{
-    sp<ProClient> clientPro;
+bool CameraService::evictClientIdByRemote(const wp<IBinder>& remote) {
+    const int callingPid = getCallingPid();
+    const int servicePid = getpid();
+    bool ret = false;
+    {
+        // Acquire mServiceLock and prevent other clients from connecting
+        std::unique_ptr<AutoConditionLock> lock =
+                AutoConditionLock::waitAndAcquire(mServiceLockWrapper);
 
-    for (int i = 0; i < mNumberOfCameras; ++i) {
-        Vector<size_t> removeIdx;
 
-        for (size_t j = 0; j < mProClientList[i].size(); ++j) {
-            wp<ProClient> cl = mProClientList[i][j];
+        std::vector<sp<BasicClient>> evicted;
+        for (auto& i : mActiveClientManager.getAll()) {
+            auto clientSp = i->getValue();
+            if (clientSp.get() == nullptr) {
+                ALOGE("%s: Dead client still in mActiveClientManager.", __FUNCTION__);
+                mActiveClientManager.remove(i);
+                continue;
+            }
+            if (remote == clientSp->getRemote() && (callingPid == servicePid ||
+                    callingPid == clientSp->getClientPid())) {
+                mActiveClientManager.remove(i);
+                evicted.push_back(clientSp);
 
-            sp<ProClient> clStrong = cl.promote();
-            if (clStrong != NULL && clStrong->getRemote() == cameraCallbacksRemote) {
-                clientPro = clStrong;
-                break;
-            } else if (clStrong == NULL) {
-                // mark to clean up dead ptr
-                removeIdx.push(j);
+                // Notify the client of disconnection
+                clientSp->notifyError(ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
+                        CaptureResultExtras());
             }
         }
 
-        // remove stale ptrs (in reverse so the indices dont change)
-        for (ssize_t j = (ssize_t)removeIdx.size() - 1; j >= 0; --j) {
-            mProClientList[i].removeAt(removeIdx[j]);
+        // Do not hold mServiceLock while disconnecting clients, but retain the condition blocking
+        // other clients from connecting in mServiceLockWrapper if held
+        mServiceLock.unlock();
+
+        for (auto& i : evicted) {
+            if (i.get() != nullptr) {
+                i->disconnect();
+                ret = true;
+            }
         }
 
-    }
+        // Reacquire mServiceLock
+        mServiceLock.lock();
 
-    return clientPro;
+    } // lock is destroyed, allow further connect calls
+
+    return ret;
 }
 
-sp<CameraService::BasicClient> CameraService::findClientUnsafe(
-                        const wp<IBinder>& cameraClient, int& outIndex) {
-    sp<BasicClient> client;
 
-    for (int i = 0; i < mNumberOfCameras; i++) {
-
-        // This happens when we have already disconnected (or this is
-        // just another unused camera).
-        if (mClient[i] == 0) continue;
-
-        // Promote mClient. It can fail if we are called from this path:
-        // Client::~Client() -> disconnect() -> removeClientByRemote().
-        client = mClient[i].promote();
-
-        // Clean up stale client entry
-        if (client == NULL) {
-            mClient[i].clear();
-            continue;
-        }
-
-        if (cameraClient == client->getRemote()) {
-            // Found our camera
-            outIndex = i;
-            return client;
+std::shared_ptr<CameraService::CameraState> CameraService::getCameraState(
+        const String8& cameraId) const {
+    std::shared_ptr<CameraState> state;
+    {
+        Mutex::Autolock lock(mCameraStatesLock);
+        auto iter = mCameraStates.find(cameraId);
+        if (iter != mCameraStates.end()) {
+            state = iter->second;
         }
     }
-
-    outIndex = -1;
-    return NULL;
+    return state;
 }
 
-CameraService::BasicClient* CameraService::getClientByIdUnsafe(int cameraId) {
-    if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
-    return mClient[cameraId].unsafe_get();
+sp<CameraService::BasicClient> CameraService::removeClientLocked(const String8& cameraId) {
+    // Remove from active clients list
+    auto clientDescriptorPtr = mActiveClientManager.remove(cameraId);
+    if (clientDescriptorPtr == nullptr) {
+        ALOGW("%s: Could not evict client, no client for camera ID %s", __FUNCTION__,
+                cameraId.string());
+        return sp<BasicClient>{nullptr};
+    }
+
+    return clientDescriptorPtr->getValue();
 }
 
-Mutex* CameraService::getClientLockById(int cameraId) {
-    if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
-    return &mClientLock[cameraId];
+
+void CameraService::logDisconnected(const String8& cameraId, int clientPid,
+        const String8& clientPackage) {
+
+    String8 curTime = getFormattedCurrentTime();
+    // Log the clients evicted
+    mEventLog.add(String8::format("%s : DISCONNECT device %s client for package %s (PID %d)",
+            curTime.string(), cameraId.string(), clientPackage.string(), clientPid));
 }
 
-sp<CameraService::BasicClient> CameraService::getClientByRemote(
-                                const wp<IBinder>& cameraClient) {
+void CameraService::logConnected(const String8& cameraId, int clientPid,
+        const String8& clientPackage) {
 
-    // Declare this before the lock to make absolutely sure the
-    // destructor won't be called with the lock held.
-    sp<BasicClient> client;
-
-    Mutex::Autolock lock(mServiceLock);
-
-    int outIndex;
-    client = findClientUnsafe(cameraClient, outIndex);
-
-    return client;
+    String8 curTime = getFormattedCurrentTime();
+    // Log the clients evicted
+    mEventLog.add(String8::format("%s : CONNECT device %s client for package %s (PID %d)",
+            curTime.string(), cameraId.string(), clientPackage.string(), clientPid));
 }
 
 status_t CameraService::onTransact(
@@ -1289,24 +1449,6 @@
     return BnCameraService::onTransact(code, data, reply, flags);
 }
 
-// The reason we need this busy bit is a new CameraService::connect() request
-// may come in while the previous Client's destructor has not been run or is
-// still running. If the last strong reference of the previous Client is gone
-// but the destructor has not been finished, we should not allow the new Client
-// to be created because we need to wait for the previous Client to tear down
-// the hardware first.
-void CameraService::setCameraBusy(int cameraId) {
-    android_atomic_write(1, &mBusy[cameraId]);
-
-    ALOGV("setCameraBusy cameraId=%d", cameraId);
-}
-
-void CameraService::setCameraFree(int cameraId) {
-    android_atomic_write(0, &mBusy[cameraId]);
-
-    ALOGV("setCameraFree cameraId=%d", cameraId);
-}
-
 // We share the media players for shutter and recording sound for all clients.
 // A reference count is kept to determine when we will actually release the
 // media players.
@@ -1363,7 +1505,8 @@
         int cameraId, int cameraFacing,
         int clientPid, uid_t clientUid,
         int servicePid) :
-        CameraService::BasicClient(cameraService, cameraClient->asBinder(),
+        CameraService::BasicClient(cameraService,
+                IInterface::asBinder(cameraClient),
                 clientPackageName,
                 cameraId, cameraFacing,
                 clientPid, clientUid,
@@ -1374,7 +1517,6 @@
 
     mRemoteCallback = cameraClient;
 
-    cameraService->setCameraBusy(cameraId);
     cameraService->loadSound();
 
     LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
@@ -1396,7 +1538,7 @@
         int cameraId, int cameraFacing,
         int clientPid, uid_t clientUid,
         int servicePid):
-        mClientPackageName(clientPackageName)
+        mClientPackageName(clientPackageName), mDisconnected(false)
 {
     mCameraService = cameraService;
     mRemoteBinder = remoteCallback;
@@ -1415,14 +1557,34 @@
 }
 
 void CameraService::BasicClient::disconnect() {
-    ALOGV("BasicClient::disconnect");
-    mCameraService->removeClientByRemote(mRemoteBinder);
+    if (mDisconnected) return;
+    mDisconnected = true;;
+
+    mCameraService->removeByClient(this);
+    mCameraService->logDisconnected(String8::format("%d", mCameraId), mClientPid,
+            String8(mClientPackageName));
+
+    sp<IBinder> remote = getRemote();
+    if (remote != nullptr) {
+        remote->unlinkToDeath(mCameraService);
+    }
 
     finishCameraOps();
+    ALOGI("%s: Disconnected client for camera %d for PID %d", __FUNCTION__, mCameraId, mClientPid);
+
     // client shouldn't be able to call into us anymore
     mClientPid = 0;
 }
 
+String16 CameraService::BasicClient::getPackageName() const {
+    return mClientPackageName;
+}
+
+
+int CameraService::BasicClient::getClientPid() const {
+    return mClientPid;
+}
+
 status_t CameraService::BasicClient::startCameraOps() {
     int32_t res;
     // Notify app ops that the camera is not available
@@ -1448,7 +1610,7 @@
 
     // Transition device availability listeners from PRESENT -> NOT_AVAILABLE
     mCameraService->updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
-            mCameraId);
+            String8::format("%d", mCameraId));
 
     return OK;
 }
@@ -1461,22 +1623,21 @@
                 mClientPackageName);
         mOpsActive = false;
 
-        // Notify device availability listeners that this camera is available
-        // again
+        auto rejected = {ICameraServiceListener::STATUS_NOT_PRESENT,
+                ICameraServiceListener::STATUS_ENUMERATING};
 
-        StatusVector rejectSourceStates;
-        rejectSourceStates.push_back(ICameraServiceListener::STATUS_NOT_PRESENT);
-        rejectSourceStates.push_back(ICameraServiceListener::STATUS_ENUMERATING);
-
-        // Transition to PRESENT if the camera is not in either of above 2
-        // states
+        // Transition to PRESENT if the camera is not in either of the rejected states
         mCameraService->updateStatus(ICameraServiceListener::STATUS_PRESENT,
-                mCameraId,
-                &rejectSourceStates);
+                String8::format("%d", mCameraId), rejected);
 
+        // Notify flashlight that a camera device is closed.
+        mCameraService->mFlashlight->deviceClosed(
+                String8::format("%d", mCameraId));
     }
     // Always stop watching, even if no camera op is active
-    mAppOpsManager.stopWatchingMode(mOpsCallback);
+    if (mOpsCallback != NULL) {
+        mAppOpsManager.stopWatchingMode(mOpsCallback);
+    }
     mOpsCallback.clear();
 
     return OK;
@@ -1514,26 +1675,15 @@
 
 // ----------------------------------------------------------------------------
 
-Mutex* CameraService::Client::getClientLockFromCookie(void* user) {
-    return gCameraService->getClientLockById((int)(intptr_t) user);
-}
-
-// Provide client pointer for callbacks. Client lock returned from getClientLockFromCookie should
-// be acquired for this to be safe
-CameraService::Client* CameraService::Client::getClientFromCookie(void* user) {
-    BasicClient *basicClient = gCameraService->getClientByIdUnsafe((int)(intptr_t) user);
-    // OK: only CameraClient calls this, and they already cast anyway.
-    Client* client = static_cast<Client*>(basicClient);
-
-    // This could happen if the Client is in the process of shutting down (the
-    // last strong reference is gone, but the destructor hasn't finished
-    // stopping the hardware).
-    if (client == NULL) return NULL;
-
-    // destruction already started, so should not be accessed
-    if (client->mDestructionStarted) return NULL;
-
-    return client;
+// Provide client strong pointer for callbacks.
+sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) {
+    String8 cameraId = String8::format("%d", (int)(intptr_t) user);
+    auto clientDescriptor = gCameraService->mActiveClientManager.get(cameraId);
+    if (clientDescriptor != nullptr) {
+        return sp<Client>{
+                static_cast<Client*>(clientDescriptor->getValue().get())};
+    }
+    return sp<Client>{nullptr};
 }
 
 void CameraService::Client::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
@@ -1545,7 +1695,6 @@
 void CameraService::Client::disconnect() {
     ALOGV("Client::disconnect");
     BasicClient::disconnect();
-    mCameraService->setCameraFree(mCameraId);
 }
 
 CameraService::Client::OpsCallback::OpsCallback(wp<BasicClient> client):
@@ -1572,7 +1721,7 @@
         int clientPid,
         uid_t clientUid,
         int servicePid)
-        : CameraService::BasicClient(cameraService, remoteCallback->asBinder(),
+        : CameraService::BasicClient(cameraService, IInterface::asBinder(remoteCallback),
                 clientPackageName, cameraId, cameraFacing,
                 clientPid,  clientUid, servicePid)
 {
@@ -1588,6 +1737,104 @@
 }
 
 // ----------------------------------------------------------------------------
+//                  CameraState
+// ----------------------------------------------------------------------------
+
+CameraService::CameraState::CameraState(const String8& id, int cost,
+        const std::set<String8>& conflicting) : mId(id),
+        mStatus(ICameraServiceListener::STATUS_PRESENT), mCost(cost), mConflicting(conflicting) {}
+
+CameraService::CameraState::~CameraState() {}
+
+ICameraServiceListener::Status CameraService::CameraState::getStatus() const {
+    Mutex::Autolock lock(mStatusLock);
+    return mStatus;
+}
+
+CameraParameters CameraService::CameraState::getShimParams() const {
+    return mShimParams;
+}
+
+void CameraService::CameraState::setShimParams(const CameraParameters& params) {
+    mShimParams = params;
+}
+
+int CameraService::CameraState::getCost() const {
+    return mCost;
+}
+
+std::set<String8> CameraService::CameraState::getConflicting() const {
+    return mConflicting;
+}
+
+String8 CameraService::CameraState::getId() const {
+    return mId;
+}
+
+// ----------------------------------------------------------------------------
+//                  CameraClientManager
+// ----------------------------------------------------------------------------
+
+CameraService::CameraClientManager::~CameraClientManager() {}
+
+sp<CameraService::BasicClient> CameraService::CameraClientManager::getCameraClient(
+        const String8& id) const {
+    auto descriptor = get(id);
+    if (descriptor == nullptr) {
+        return sp<BasicClient>{nullptr};
+    }
+    return descriptor->getValue();
+}
+
+String8 CameraService::CameraClientManager::toString() const {
+    auto all = getAll();
+    String8 ret("[");
+    bool hasAny = false;
+    for (auto& i : all) {
+        hasAny = true;
+        String8 key = i->getKey();
+        int32_t cost = i->getCost();
+        int32_t pid = i->getOwnerId();
+        int32_t priority = i->getPriority();
+        auto conflicting = i->getConflicting();
+        auto clientSp = i->getValue();
+        String8 packageName;
+        if (clientSp.get() != nullptr) {
+            packageName = String8{clientSp->getPackageName()};
+        }
+        ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Priority: %"
+                PRId32 ", ", key.string(), cost, pid, priority);
+
+        if (packageName.size() != 0) {
+            ret.appendFormat("Client Package Name: %s", packageName.string());
+        }
+
+        ret.append(", Conflicting Client Devices: {");
+        for (auto& j : conflicting) {
+            ret.appendFormat("%s, ", j.string());
+        }
+        ret.append("})");
+    }
+    if (hasAny) ret.append("\n");
+    ret.append("]\n");
+    return ret;
+}
+
+CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
+        const String8& key, const sp<BasicClient>& value, int32_t cost,
+        const std::set<String8>& conflictingKeys, int32_t priority, int32_t ownerId) {
+
+    return std::make_shared<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>(
+            key, value, cost, conflictingKeys, priority, ownerId);
+}
+
+CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
+        const sp<BasicClient>& value, const CameraService::DescriptorPtr& partial) {
+    return makeClientDescriptor(partial->getKey(), value, partial->getCost(),
+            partial->getConflicting(), partial->getPriority(), partial->getOwnerId());
+}
+
+// ----------------------------------------------------------------------------
 
 static const int kDumpLockRetries = 50;
 static const int kDumpLockSleep = 60000;
@@ -1629,15 +1876,15 @@
             return NO_ERROR;
         }
 
-        result = String8::format("Camera module HAL API version: 0x%x\n",
-                mModule->common.hal_api_version);
-        result.appendFormat("Camera module API version: 0x%x\n",
-                mModule->common.module_api_version);
-        result.appendFormat("Camera module name: %s\n",
-                mModule->common.name);
-        result.appendFormat("Camera module author: %s\n",
-                mModule->common.author);
-        result.appendFormat("Number of camera devices: %d\n\n", mNumberOfCameras);
+        const hw_module_t* common = mModule->getRawModule();
+        result = String8::format("Camera module HAL API version: %#x\n", common->hal_api_version);
+        result.appendFormat("Camera module API version: %#x\n", common->module_api_version);
+        result.appendFormat("Camera module name: %s\n", common->name);
+        result.appendFormat("Camera module author: %s\n", common->author);
+        result.appendFormat("Number of camera devices: %d\n", mNumberOfCameras);
+        String8 activeClientString = mActiveClientManager.toString();
+        result.appendFormat("Active Camera Clients:\n%s", activeClientString.string());
+
 
         sp<VendorTagDescriptor> desc = VendorTagDescriptor::getGlobalVendorTagDescriptor();
         if (desc == NULL) {
@@ -1652,11 +1899,31 @@
             desc->dump(fd, /*verbosity*/2, /*indentation*/4);
         }
 
-        for (int i = 0; i < mNumberOfCameras; i++) {
-            result = String8::format("Camera %d static information:\n", i);
+        result = String8("Prior client events (most recent at top):\n");
+
+        for (const auto& msg : mEventLog) {
+            result.appendFormat("%s\n", msg.string());
+        }
+
+        if (mEventLog.size() == DEFAULT_EVICTION_LOG_LENGTH) {
+            result.append("...\n");
+        }
+
+        write(fd, result.string(), result.size());
+
+        bool stateLocked = tryLock(mCameraStatesLock);
+        if (!stateLocked) {
+            result = String8::format("CameraStates in use, may be deadlocked\n");
+            write(fd, result.string(), result.size());
+        }
+
+        for (auto& state : mCameraStates) {
+            String8 cameraId = state.first;
+            result = String8::format("Camera %s information:\n", cameraId.string());
             camera_info info;
 
-            status_t rc = mModule->get_camera_info(i, &info);
+            // TODO: Change getCameraInfo + HAL to use String cameraIds
+            status_t rc = mModule->getCameraInfo(cameraIdToInt(cameraId), &info);
             if (rc != OK) {
                 result.appendFormat("  Error reading static information!\n");
                 write(fd, result.string(), result.size());
@@ -1665,13 +1932,24 @@
                         info.facing == CAMERA_FACING_BACK ? "BACK" : "FRONT");
                 result.appendFormat("  Orientation: %d\n", info.orientation);
                 int deviceVersion;
-                if (mModule->common.module_api_version <
-                        CAMERA_MODULE_API_VERSION_2_0) {
+                if (common->module_api_version < CAMERA_MODULE_API_VERSION_2_0) {
                     deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
                 } else {
                     deviceVersion = info.device_version;
                 }
-                result.appendFormat("  Device version: 0x%x\n", deviceVersion);
+
+                auto conflicting = state.second->getConflicting();
+                result.appendFormat("  Resource Cost: %d\n", state.second->getCost());
+                result.appendFormat("  Conflicting Devices:");
+                for (auto& id : conflicting) {
+                    result.appendFormat(" %s", cameraId.string());
+                }
+                if (conflicting.size() == 0) {
+                    result.appendFormat(" NONE");
+                }
+                result.appendFormat("\n");
+
+                result.appendFormat("  Device version: %#x\n", deviceVersion);
                 if (deviceVersion >= CAMERA_DEVICE_API_VERSION_2_0) {
                     result.appendFormat("  Device static metadata:\n");
                     write(fd, result.string(), result.size());
@@ -1680,19 +1958,38 @@
                 } else {
                     write(fd, result.string(), result.size());
                 }
+
+                CameraParameters p = state.second->getShimParams();
+                if (!p.isEmpty()) {
+                    result = String8::format("  Camera1 API shim is using parameters:\n        ");
+                    write(fd, result.string(), result.size());
+                    p.dump(fd, args);
+                }
             }
 
-            sp<BasicClient> client = mClient[i].promote();
-            if (client == 0) {
-                result = String8::format("  Device is closed, no client instance\n");
+            auto clientDescriptor = mActiveClientManager.get(cameraId);
+            if (clientDescriptor == nullptr) {
+                result = String8::format("  Device %s is closed, no client instance\n",
+                        cameraId.string());
                 write(fd, result.string(), result.size());
                 continue;
             }
             hasClient = true;
-            result = String8::format("  Device is open. Client instance dump:\n");
+            result = String8::format("  Device %s is open. Client instance dump:\n\n",
+                    cameraId.string());
+            result.appendFormat("Client priority level: %d\n", clientDescriptor->getPriority());
+            result.appendFormat("Client PID: %d\n", clientDescriptor->getOwnerId());
+
+            auto client = clientDescriptor->getValue();
+            result.appendFormat("Client package: %s\n",
+                    String8(client->getPackageName()).string());
             write(fd, result.string(), result.size());
+
             client->dump(fd, args);
         }
+
+        if (stateLocked) mCameraStatesLock.unlock();
+
         if (!hasClient) {
             result = String8::format("\nNo active camera clients yet.\n");
             write(fd, result.string(), result.size());
@@ -1716,112 +2013,119 @@
                 write(fd, result.string(), result.size());
             }
         }
-
     }
     return NO_ERROR;
 }
 
-/*virtual*/void CameraService::binderDied(
-    const wp<IBinder> &who) {
+void CameraService::handleTorchClientBinderDied(const wp<IBinder> &who) {
+    Mutex::Autolock al(mTorchClientMapMutex);
+    for (size_t i = 0; i < mTorchClientMap.size(); i++) {
+        if (mTorchClientMap[i] == who) {
+            // turn off the torch mode that was turned on by dead client
+            String8 cameraId = mTorchClientMap.keyAt(i);
+            status_t res = mFlashlight->setTorchMode(cameraId, false);
+            if (res) {
+                ALOGE("%s: torch client died but couldn't turn off torch: "
+                    "%s (%d)", __FUNCTION__, strerror(-res), res);
+                return;
+            }
+            mTorchClientMap.removeItemsAt(i);
+            break;
+        }
+    }
+}
+
+/*virtual*/void CameraService::binderDied(const wp<IBinder> &who) {
 
     /**
       * While tempting to promote the wp<IBinder> into a sp,
       * it's actually not supported by the binder driver
       */
 
-    ALOGV("java clients' binder died");
+    // check torch client
+    handleTorchClientBinderDied(who);
 
-    sp<BasicClient> cameraClient = getClientByRemote(who);
-
-    if (cameraClient == 0) {
-        ALOGV("java clients' binder death already cleaned up (normal case)");
+    // check camera device client
+    if(!evictClientIdByRemote(who)) {
+        ALOGV("%s: Java client's binder death already cleaned up (normal case)", __FUNCTION__);
         return;
     }
 
-    ALOGW("Disconnecting camera client %p since the binder for it "
-          "died (this pid %d)", cameraClient.get(), getCallingPid());
-
-    cameraClient->disconnect();
-
+    ALOGE("%s: Java client's binder died, removing it from the list of active clients",
+            __FUNCTION__);
 }
 
-void CameraService::updateStatus(ICameraServiceListener::Status status,
-                                 int32_t cameraId,
-                                 const StatusVector *rejectSourceStates) {
-    // do not lock mServiceLock here or can get into a deadlock from
-    //  connect() -> ProClient::disconnect -> updateStatus
-    Mutex::Autolock lock(mStatusMutex);
-
-    ICameraServiceListener::Status oldStatus = mStatusList[cameraId];
-
-    mStatusList[cameraId] = status;
-
-    if (oldStatus != status) {
-        ALOGV("%s: Status has changed for camera ID %d from 0x%x to 0x%x",
-              __FUNCTION__, cameraId, (uint32_t)oldStatus, (uint32_t)status);
-
-        if (oldStatus == ICameraServiceListener::STATUS_NOT_PRESENT &&
-            (status != ICameraServiceListener::STATUS_PRESENT &&
-             status != ICameraServiceListener::STATUS_ENUMERATING)) {
-
-            ALOGW("%s: From NOT_PRESENT can only transition into PRESENT"
-                  " or ENUMERATING", __FUNCTION__);
-            mStatusList[cameraId] = oldStatus;
-            return;
-        }
-
-        if (rejectSourceStates != NULL) {
-            const StatusVector &rejectList = *rejectSourceStates;
-            StatusVector::const_iterator it = rejectList.begin();
-
-            /**
-             * Sometimes we want to conditionally do a transition.
-             * For example if a client disconnects, we want to go to PRESENT
-             * only if we weren't already in NOT_PRESENT or ENUMERATING.
-             */
-            for (; it != rejectList.end(); ++it) {
-                if (oldStatus == *it) {
-                    ALOGV("%s: Rejecting status transition for Camera ID %d, "
-                          " since the source state was was in one of the bad "
-                          " states.", __FUNCTION__, cameraId);
-                    mStatusList[cameraId] = oldStatus;
-                    return;
-                }
-            }
-        }
-
-        /**
-          * ProClients lose their exclusive lock.
-          * - Done before the CameraClient can initialize the HAL device,
-          *   since we want to be able to close it before they get to initialize
-          */
-        if (status == ICameraServiceListener::STATUS_NOT_AVAILABLE) {
-            Vector<wp<ProClient> > proClients(mProClientList[cameraId]);
-            Vector<wp<ProClient> >::const_iterator it;
-
-            for (it = proClients.begin(); it != proClients.end(); ++it) {
-                sp<ProClient> proCl = it->promote();
-                if (proCl.get() != NULL) {
-                    proCl->onExclusiveLockStolen();
-                }
-            }
-        }
-
-        Vector<sp<ICameraServiceListener> >::const_iterator it;
-        for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
-            (*it)->onStatusChanged(status, cameraId);
-        }
-    }
+void CameraService::updateStatus(ICameraServiceListener::Status status, const String8& cameraId) {
+    updateStatus(status, cameraId, {});
 }
 
-ICameraServiceListener::Status CameraService::getStatus(int cameraId) const {
-    if (cameraId < 0 || cameraId >= MAX_CAMERAS) {
-        ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
-        return ICameraServiceListener::STATUS_UNKNOWN;
+void CameraService::updateStatus(ICameraServiceListener::Status status, const String8& cameraId,
+        std::initializer_list<ICameraServiceListener::Status> rejectSourceStates) {
+    // Do not lock mServiceLock here or can get into a deadlock from
+    // connect() -> disconnect -> updateStatus
+
+    auto state = getCameraState(cameraId);
+
+    if (state == nullptr) {
+        ALOGW("%s: Could not update the status for %s, no such device exists", __FUNCTION__,
+                cameraId.string());
+        return;
     }
 
-    Mutex::Autolock al(mStatusMutex);
-    return mStatusList[cameraId];
+    // Update the status for this camera state, then send the onStatusChangedCallbacks to each
+    // of the listeners with both the mStatusStatus and mStatusListenerLock held
+    state->updateStatus(status, cameraId, rejectSourceStates, [this]
+            (const String8& cameraId, ICameraServiceListener::Status status) {
+
+            // Update torch status
+            if (status == ICameraServiceListener::STATUS_NOT_PRESENT ||
+                status == ICameraServiceListener::STATUS_NOT_AVAILABLE) {
+                // Update torch status to not available when the camera device becomes not present
+                // or not available.
+                onTorchStatusChanged(cameraId, ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE);
+            } else if (status == ICameraServiceListener::STATUS_PRESENT) {
+                // Update torch status to available when the camera device becomes present or
+                // available
+                onTorchStatusChanged(cameraId, ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF);
+            }
+
+            Mutex::Autolock lock(mStatusListenerLock);
+
+            for (auto& listener : mListenerList) {
+                // TODO: Refactor status listeners to use strings for Camera IDs and remove this.
+                int id = cameraIdToInt(cameraId);
+                if (id != -1) listener->onStatusChanged(status, id);
+            }
+        });
+}
+
+status_t CameraService::getTorchStatusLocked(
+        const String8& cameraId,
+        ICameraServiceListener::TorchStatus *status) const {
+    if (!status) {
+        return BAD_VALUE;
+    }
+    ssize_t index = mTorchStatusMap.indexOfKey(cameraId);
+    if (index == NAME_NOT_FOUND) {
+        // invalid camera ID or the camera doesn't have a flash unit
+        return NAME_NOT_FOUND;
+    }
+
+    *status = mTorchStatusMap.valueAt(index);
+    return OK;
+}
+
+status_t CameraService::setTorchStatusLocked(const String8& cameraId,
+        ICameraServiceListener::TorchStatus status) {
+    ssize_t index = mTorchStatusMap.indexOfKey(cameraId);
+    if (index == NAME_NOT_FOUND) {
+        return BAD_VALUE;
+    }
+    ICameraServiceListener::TorchStatus& item =
+            mTorchStatusMap.editValueAt(index);
+    item = status;
+
+    return OK;
 }
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index a7328cf..53420e5 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -36,9 +36,17 @@
 #include <camera/CameraParameters.h>
 
 #include <camera/ICameraServiceListener.h>
+#include "CameraFlashlight.h"
 
-/* This needs to be increased if we can have more cameras */
-#define MAX_CAMERAS 2
+#include "common/CameraModule.h"
+#include "utils/AutoConditionLock.h"
+#include "utils/ClientManager.h"
+#include "utils/RingBuffer.h"
+
+#include <set>
+#include <string>
+#include <map>
+#include <memory>
 
 namespace android {
 
@@ -58,6 +66,34 @@
     class Client;
     class BasicClient;
 
+    enum apiLevel {
+        API_1 = 1,
+        API_2 = 2
+    };
+
+    // Process States (mirrors frameworks/base/core/java/android/app/ActivityManager.java)
+    static const int PROCESS_STATE_NONEXISTENT = -1;
+    static const int PROCESS_STATE_PERSISTENT = 0;
+    static const int PROCESS_STATE_PERSISTENT_UI = 1;
+    static const int PROCESS_STATE_TOP = 2;
+    static const int PROCESS_STATE_IMPORTANT_FOREGROUND = 3;
+    static const int PROCESS_STATE_IMPORTANT_BACKGROUND = 4;
+    static const int PROCESS_STATE_BACKUP = 5;
+    static const int PROCESS_STATE_HEAVY_WEIGHT = 6;
+    static const int PROCESS_STATE_SERVICE = 7;
+    static const int PROCESS_STATE_RECEIVER = 8;
+    static const int PROCESS_STATE_HOME = 9;
+    static const int PROCESS_STATE_LAST_ACTIVITY = 10;
+    static const int PROCESS_STATE_CACHED_ACTIVITY = 11;
+    static const int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 12;
+    static const int PROCESS_STATE_CACHED_EMPTY = 13;
+
+    // 3 second busy timeout when other clients are connecting
+    static const nsecs_t DEFAULT_CONNECT_TIMEOUT_NS = 3000000000;
+
+    // Default number of messages to store in eviction log
+    static const size_t DEFAULT_EVICTION_LOG_LENGTH = 50;
+
     // Implementation of BinderService<T>
     static char const* getServiceName() { return "media.camera"; }
 
@@ -66,8 +102,11 @@
 
     /////////////////////////////////////////////////////////////////////
     // HAL Callbacks
-    virtual void        onDeviceStatusChanged(int cameraId,
-                                              int newStatus);
+    virtual void        onDeviceStatusChanged(camera_device_status_t cameraId,
+                                              camera_device_status_t newStatus);
+    virtual void        onTorchStatusChanged(const String8& cameraId,
+                                             ICameraServiceListener::TorchStatus
+                                                   newStatus);
 
     /////////////////////////////////////////////////////////////////////
     // ICameraService
@@ -110,6 +149,9 @@
             /*out*/
             String16* parameters);
 
+    virtual status_t    setTorchMode(const String16& cameraId, bool enabled,
+            const sp<IBinder>& clientBinder);
+
     // OK = supports api of that version, -EOPNOTSUPP = does not support
     virtual status_t    supportsCameraApi(
             int cameraId, int apiVersion);
@@ -122,7 +164,6 @@
 
     /////////////////////////////////////////////////////////////////////
     // Client functionality
-    virtual void        removeClientByRemote(const wp<IBinder>& remoteBinder);
 
     enum sound_kind {
         SOUND_SHUTTER = 0,
@@ -140,20 +181,14 @@
 
     /////////////////////////////////////////////////////////////////////
     // Shared utilities
-    static status_t     filterOpenErrorCode(status_t err);
     static status_t     filterGetInfoErrorCode(status_t err);
 
     /////////////////////////////////////////////////////////////////////
     // CameraClient functionality
 
-    // returns plain pointer of client. Note that mClientLock should be acquired to
-    // prevent the client from destruction. The result can be NULL.
-    virtual BasicClient* getClientByIdUnsafe(int cameraId);
-    virtual Mutex*      getClientLockById(int cameraId);
-
     class BasicClient : public virtual RefBase {
     public:
-        virtual status_t    initialize(camera_module_t *module) = 0;
+        virtual status_t    initialize(CameraModule *module) = 0;
         virtual void        disconnect();
 
         // because we can't virtually inherit IInterface, which breaks
@@ -167,6 +202,15 @@
 
         virtual status_t    dump(int fd, const Vector<String16>& args) = 0;
 
+        // Return the package name for this client
+        virtual String16 getPackageName() const;
+
+        // Notify client about a fatal error
+        virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
+                const CaptureResultExtras& resultExtras) = 0;
+
+        // Get the PID of the application client using this
+        virtual int getClientPid() const;
     protected:
         BasicClient(const sp<CameraService>& cameraService,
                 const sp<IBinder>& remoteCallback,
@@ -193,6 +237,7 @@
         pid_t                           mClientPid;
         uid_t                           mClientUid;      // immutable after constructor
         pid_t                           mServicePid;     // immutable after constructor
+        bool                            mDisconnected;
 
         // - The app-side Binder interface to receive callbacks from us
         sp<IBinder>                     mRemoteBinder;   // immutable after constructor
@@ -201,10 +246,6 @@
         status_t                        startCameraOps();
         status_t                        finishCameraOps();
 
-        // Notify client about a fatal error
-        virtual void                    notifyError(
-                ICameraDeviceCallbacks::CameraErrorCode errorCode,
-                const CaptureResultExtras& resultExtras) = 0;
     private:
         AppOpsManager                   mAppOpsManager;
 
@@ -273,16 +314,14 @@
         }
 
         virtual sp<IBinder> asBinderWrapper() {
-            return asBinder();
+            return asBinder(this);
         }
 
-    protected:
-        static Mutex*        getClientLockFromCookie(void* user);
-        // convert client from cookie. Client lock should be acquired before getting Client.
-        static Client*       getClientFromCookie(void* user);
-
         virtual void         notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
                                          const CaptureResultExtras& resultExtras);
+    protected:
+        // Convert client from cookie.
+        static sp<CameraService::Client> getClientFromCookie(void* user);
 
         // Initialized in constructor
 
@@ -329,55 +368,231 @@
         // Callbacks from camera service
         virtual void          onExclusiveLockStolen() = 0;
 
-    protected:
         virtual void          notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
                                           const CaptureResultExtras& resultExtras);
+    protected:
 
         sp<IProCameraCallbacks> mRemoteCallback;
     }; // class ProClient
 
+    typedef std::shared_ptr<resource_policy::ClientDescriptor<String8,
+            sp<CameraService::BasicClient>>> DescriptorPtr;
+
+    /**
+     * A container class for managing active camera clients that are using HAL devices.  Active
+     * clients are represented by ClientDescriptor objects that contain strong pointers to the
+     * actual BasicClient subclass binder interface implementation.
+     *
+     * This class manages the eviction behavior for the camera clients.  See the parent class
+     * implementation in utils/ClientManager for the specifics of this behavior.
+     */
+    class CameraClientManager :
+            public resource_policy::ClientManager<String8, sp<CameraService::BasicClient>> {
+    public:
+        virtual ~CameraClientManager();
+
+        /**
+         * Return a strong pointer to the active BasicClient for this camera ID, or an empty
+         * if none exists.
+         */
+        sp<CameraService::BasicClient> getCameraClient(const String8& id) const;
+
+        /**
+         * Return a string describing the current state.
+         */
+        String8 toString() const;
+
+        /**
+         * Make a ClientDescriptor object wrapping the given BasicClient strong pointer.
+         */
+        static DescriptorPtr makeClientDescriptor(const String8& key, const sp<BasicClient>& value,
+                int32_t cost, const std::set<String8>& conflictingKeys, int32_t priority,
+                int32_t ownerId);
+
+        /**
+         * Make a ClientDescriptor object wrapping the given BasicClient strong pointer with
+         * values intialized from a prior ClientDescriptor.
+         */
+        static DescriptorPtr makeClientDescriptor(const sp<BasicClient>& value,
+                const CameraService::DescriptorPtr& partial);
+
+    }; // class CameraClientManager
+
 private:
 
+    /**
+     * Container class for the state of each logical camera device, including: ID, status, and
+     * dependencies on other devices.  The mapping of camera ID -> state saved in mCameraStates
+     * represents the camera devices advertised by the HAL (and any USB devices, when we add
+     * those).
+     *
+     * This container does NOT represent an active camera client.  These are represented using
+     * the ClientDescriptors stored in mActiveClientManager.
+     */
+    class CameraState {
+    public:
+        /**
+         * Make a new CameraState and set the ID, cost, and conflicting devices using the values
+         * returned in the HAL's camera_info struct for each device.
+         */
+        CameraState(const String8& id, int cost, const std::set<String8>& conflicting);
+        virtual ~CameraState();
+
+        /**
+         * Return the status for this device.
+         *
+         * This method acquires mStatusLock.
+         */
+        ICameraServiceListener::Status getStatus() const;
+
+        /**
+         * This function updates the status for this camera device, unless the given status
+         * is in the given list of rejected status states, and execute the function passed in
+         * with a signature onStatusUpdateLocked(const String8&, ICameraServiceListener::Status)
+         * if the status has changed.
+         *
+         * This method is idempotent, and will not result in the function passed to
+         * onStatusUpdateLocked being called more than once for the same arguments.
+         * This method aquires mStatusLock.
+         */
+        template<class Func>
+        void updateStatus(ICameraServiceListener::Status status, const String8& cameraId,
+                std::initializer_list<ICameraServiceListener::Status> rejectSourceStates,
+                Func onStatusUpdatedLocked);
+
+        /**
+         * Return the last set CameraParameters object generated from the information returned by
+         * the HAL for this device (or an empty CameraParameters object if none has been set).
+         */
+        CameraParameters getShimParams() const;
+
+        /**
+         * Set the CameraParameters for this device.
+         */
+        void setShimParams(const CameraParameters& params);
+
+        /**
+         * Return the resource_cost advertised by the HAL for this device.
+         */
+        int getCost() const;
+
+        /**
+         * Return a set of the IDs of conflicting devices advertised by the HAL for this device.
+         */
+        std::set<String8> getConflicting() const;
+
+        /**
+         * Return the ID of this camera device.
+         */
+        String8 getId() const;
+
+    private:
+        const String8 mId;
+        ICameraServiceListener::Status mStatus; // protected by mStatusLock
+        const int mCost;
+        std::set<String8> mConflicting;
+        mutable Mutex mStatusLock;
+        CameraParameters mShimParams;
+    }; // class CameraState
+
     // Delay-load the Camera HAL module
     virtual void onFirstRef();
 
-    // Step 1. Check if we can connect, before we acquire the service lock.
-    status_t            validateConnect(int cameraId,
-                                        /*inout*/
-                                        int& clientUid) const;
+    // Check if we can connect, before we acquire the service lock.
+    status_t validateConnect(const String8& cameraId, /*inout*/int& clientUid) const;
 
-    // Step 2. Check if we can connect, after we acquire the service lock.
-    bool                canConnectUnsafe(int cameraId,
-                                         const String16& clientPackageName,
-                                         const sp<IBinder>& remoteCallback,
-                                         /*out*/
-                                         sp<BasicClient> &client);
+    // Handle active client evictions, and update service state.
+    // Only call with with mServiceLock held.
+    status_t handleEvictionsLocked(const String8& cameraId, int clientPid,
+        apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,
+        /*out*/
+        sp<BasicClient>* client,
+        std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial);
 
-    // When connection is successful, initialize client and track its death
-    status_t            connectFinishUnsafe(const sp<BasicClient>& client,
-                                            const sp<IBinder>& remoteCallback);
+    // Single implementation shared between the various connect calls
+    template<class CALLBACK, class CLIENT>
+    status_t connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId, int halVersion,
+            const String16& clientPackageName, int clientUid, apiLevel effectiveApiLevel,
+            bool legacyMode, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
 
-    virtual sp<BasicClient>  getClientByRemote(const wp<IBinder>& cameraClient);
 
+    // Lock guarding camera service state
     Mutex               mServiceLock;
-    // either a Client or CameraDeviceClient
-    wp<BasicClient>     mClient[MAX_CAMERAS];  // protected by mServiceLock
-    Mutex               mClientLock[MAX_CAMERAS]; // prevent Client destruction inside callbacks
+
+    // Condition to use with mServiceLock, used to handle simultaneous connect calls from clients
+    std::shared_ptr<WaitableMutexWrapper> mServiceLockWrapper;
+
+    // Return NO_ERROR if the device with a give ID can be connected to
+    status_t checkIfDeviceIsUsable(const String8& cameraId) const;
+
+    // Container for managing currently active application-layer clients
+    CameraClientManager mActiveClientManager;
+
+    // Mapping from camera ID -> state for each device, map is protected by mCameraStatesLock
+    std::map<String8, std::shared_ptr<CameraState>> mCameraStates;
+
+    // Mutex guarding mCameraStates map
+    mutable Mutex mCameraStatesLock;
+
+    // Circular buffer for storing event logging for dumps
+    RingBuffer<String8> mEventLog;
+
+    /**
+     * Get the camera state for a given camera id.
+     *
+     * This acquires mCameraStatesLock.
+     */
+    std::shared_ptr<CameraService::CameraState> getCameraState(const String8& cameraId) const;
+
+    /**
+     * Evict client who's remote binder has died.  Returns true if this client was in the active
+     * list and was disconnected.
+     *
+     * This method acquires mServiceLock.
+     */
+    bool evictClientIdByRemote(const wp<IBinder>& cameraClient);
+
+    /**
+     * Remove the given client from the active clients list; does not disconnect the client.
+     *
+     * This method acquires mServiceLock.
+     */
+    void removeByClient(const BasicClient* client);
+
+    /**
+     * Add new client to active clients list after conflicting clients have disconnected using the
+     * values set in the partial descriptor passed in to construct the actual client descriptor.
+     * This is typically called at the end of a connect call.
+     *
+     * This method must be called with mServiceLock held.
+     */
+    void finishConnectLocked(const sp<BasicClient>& client, const DescriptorPtr& desc);
+
+    /**
+     * Returns the integer corresponding to the given camera ID string, or -1 on failure.
+     */
+    static int cameraIdToInt(const String8& cameraId);
+
+    /**
+     * Remove a single client corresponding to the given camera id from the list of active clients.
+     * If none exists, return an empty strongpointer.
+     *
+     * This method must be called with mServiceLock held.
+     */
+    sp<CameraService::BasicClient> removeClientLocked(const String8& cameraId);
+
+    /**
+     * Add a event log message that a client has been disconnected.
+     */
+    void logDisconnected(const String8& cameraId, int clientPid, const String8& clientPackage);
+
+    /**
+     * Add a event log message that a client has been connected.
+     */
+    void logConnected(const String8& cameraId, int clientPid, const String8& clientPackage);
+
     int                 mNumberOfCameras;
 
-    typedef wp<ProClient> weak_pro_client_ptr;
-    Vector<weak_pro_client_ptr> mProClientList[MAX_CAMERAS];
-
-    // needs to be called with mServiceLock held
-    sp<BasicClient>     findClientUnsafe(const wp<IBinder>& cameraClient, int& outIndex);
-    sp<ProClient>       findProClientUnsafe(
-                                     const wp<IBinder>& cameraCallbacksRemote);
-
-    // atomics to record whether the hardware is allocated to some client.
-    volatile int32_t    mBusy[MAX_CAMERAS];
-    void                setCameraBusy(int cameraId);
-    void                setCameraFree(int cameraId);
-
     // sounds
     MediaPlayer*        newMediaPlayer(const char *file);
 
@@ -385,45 +600,60 @@
     sp<MediaPlayer>     mSoundPlayer[NUM_SOUNDS];
     int                 mSoundRef;  // reference count (release all MediaPlayer when 0)
 
-    camera_module_t *mModule;
+    CameraModule*     mModule;
 
-    Vector<sp<ICameraServiceListener> >
-                        mListenerList;
+    // Guarded by mStatusListenerMutex
+    std::vector<sp<ICameraServiceListener>> mListenerList;
+    Mutex       mStatusListenerLock;
 
-    // guard only mStatusList and the broadcasting of ICameraServiceListener
-    mutable Mutex       mStatusMutex;
-    ICameraServiceListener::Status
-                        mStatusList[MAX_CAMERAS];
+    /**
+     * Update the status for the given camera id (if that device exists), and broadcast the
+     * status update to all current ICameraServiceListeners if the status has changed.  Any
+     * statuses in rejectedSourceStates will be ignored.
+     *
+     * This method must be idempotent.
+     * This method acquires mStatusLock and mStatusListenerLock.
+     */
+    void updateStatus(ICameraServiceListener::Status status, const String8& cameraId,
+            std::initializer_list<ICameraServiceListener::Status> rejectedSourceStates);
+    void updateStatus(ICameraServiceListener::Status status, const String8& cameraId);
 
-    // Read the current status (locks mStatusMutex)
-    ICameraServiceListener::Status
-                        getStatus(int cameraId) const;
+    // flashlight control
+    sp<CameraFlashlight> mFlashlight;
+    // guard mTorchStatusMap
+    Mutex                mTorchStatusMutex;
+    // guard mTorchClientMap
+    Mutex                mTorchClientMapMutex;
+    // camera id -> torch status
+    KeyedVector<String8, ICameraServiceListener::TorchStatus> mTorchStatusMap;
+    // camera id -> torch client binder
+    // only store the last client that turns on each camera's torch mode
+    KeyedVector<String8, sp<IBinder> > mTorchClientMap;
 
-    typedef Vector<ICameraServiceListener::Status> StatusVector;
-    // Broadcast the new status if it changed (locks the service mutex)
-    void                updateStatus(
-                            ICameraServiceListener::Status status,
-                            int32_t cameraId,
-                            const StatusVector *rejectSourceStates = NULL);
+    // check and handle if torch client's process has died
+    void handleTorchClientBinderDied(const wp<IBinder> &who);
+
+    // handle torch mode status change and invoke callbacks. mTorchStatusMutex
+    // should be locked.
+    void onTorchStatusChangedLocked(const String8& cameraId,
+            ICameraServiceListener::TorchStatus newStatus);
+
+    // get a camera's torch status. mTorchStatusMutex should be locked.
+    status_t getTorchStatusLocked(const String8 &cameraId,
+            ICameraServiceListener::TorchStatus *status) const;
+
+    // set a camera's torch status. mTorchStatusMutex should be locked.
+    status_t setTorchStatusLocked(const String8 &cameraId,
+            ICameraServiceListener::TorchStatus status);
 
     // IBinder::DeathRecipient implementation
     virtual void        binderDied(const wp<IBinder> &who);
 
     // Helpers
 
-    bool                isValidCameraId(int cameraId);
-
     bool                setUpVendorTags();
 
     /**
-     * A mapping of camera ids to CameraParameters returned by that camera device.
-     *
-     * This cache is used to generate CameraCharacteristic metadata when using
-     * the HAL1 shim.
-     */
-    KeyedVector<int, CameraParameters>    mShimParams;
-
-    /**
      * Initialize and cache the metadata used by the HAL1 shim for a given cameraId.
      *
      * Returns OK on success, or a negative error code.
@@ -446,25 +676,190 @@
      */
     status_t            generateShimMetadata(int cameraId, /*out*/CameraMetadata* cameraInfo);
 
+    static int getCallingPid();
+
+    static int getCallingUid();
+
     /**
-     * Connect a new camera client.  This should only be used while holding the
-     * mutex for mServiceLock.
-     *
-     * Returns OK on success, or a negative error code.
+     * Get the current system time as a formatted string.
      */
-    status_t            connectHelperLocked(
-            /*out*/
-            sp<Client>& client,
-            /*in*/
-            const sp<ICameraClient>& cameraClient,
-            int cameraId,
-            const String16& clientPackageName,
-            int clientUid,
-            int callingPid,
-            int halVersion = CAMERA_HAL_API_VERSION_UNSPECIFIED,
-            bool legacyMode = false);
+    static String8 getFormattedCurrentTime();
+
+    /**
+     * Get the camera eviction priority from the current process state given by ActivityManager.
+     */
+    static int getCameraPriorityFromProcState(int procState);
+
+    static status_t makeClient(const sp<CameraService>& cameraService,
+            const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
+            int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
+            int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
+            /*out*/sp<BasicClient>* client);
 };
 
+template<class Func>
+void CameraService::CameraState::updateStatus(ICameraServiceListener::Status status,
+        const String8& cameraId,
+        std::initializer_list<ICameraServiceListener::Status> rejectSourceStates,
+        Func onStatusUpdatedLocked) {
+    Mutex::Autolock lock(mStatusLock);
+    ICameraServiceListener::Status oldStatus = mStatus;
+    mStatus = status;
+
+    if (oldStatus == status) {
+        return;
+    }
+
+    ALOGV("%s: Status has changed for camera ID %s from %#x to %#x", __FUNCTION__,
+            cameraId.string(), oldStatus, status);
+
+    if (oldStatus == ICameraServiceListener::STATUS_NOT_PRESENT &&
+        (status != ICameraServiceListener::STATUS_PRESENT &&
+         status != ICameraServiceListener::STATUS_ENUMERATING)) {
+
+        ALOGW("%s: From NOT_PRESENT can only transition into PRESENT or ENUMERATING",
+                __FUNCTION__);
+        mStatus = oldStatus;
+        return;
+    }
+
+    /**
+     * Sometimes we want to conditionally do a transition.
+     * For example if a client disconnects, we want to go to PRESENT
+     * only if we weren't already in NOT_PRESENT or ENUMERATING.
+     */
+    for (auto& rejectStatus : rejectSourceStates) {
+        if (oldStatus == rejectStatus) {
+            ALOGV("%s: Rejecting status transition for Camera ID %s,  since the source "
+                    "state was was in one of the bad states.", __FUNCTION__, cameraId.string());
+            mStatus = oldStatus;
+            return;
+        }
+    }
+
+    onStatusUpdatedLocked(cameraId, status);
+}
+
+
+template<class CALLBACK, class CLIENT>
+status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
+        int halVersion, const String16& clientPackageName, int clientUid,
+        apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
+        /*out*/sp<CLIENT>& device) {
+    status_t ret = NO_ERROR;
+    String8 clientName8(clientPackageName);
+    int clientPid = getCallingPid();
+
+    ALOGI("CameraService::connect call E (PID %d \"%s\", camera ID %s) for HAL version %d and "
+            "Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
+            halVersion, static_cast<int>(effectiveApiLevel));
+
+    // Enforce client permissions and do basic sanity checks
+    if((ret = validateConnect(cameraId, /*inout*/clientUid)) != NO_ERROR) {
+        return ret;
+    }
+
+    sp<CLIENT> client = nullptr;
+    {
+        // Acquire mServiceLock and prevent other clients from connecting
+        std::unique_ptr<AutoConditionLock> lock =
+                AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
+        if (lock == nullptr) {
+            ALOGE("CameraService::connect X (PID %d) rejected (too many other clients connecting)."
+                    , clientPid);
+            return -EBUSY;
+        }
+
+        // Check the shim parameters after acquiring lock, if they have already been updated and
+        // we were doing a shim update, return immediately
+        if (shimUpdateOnly) {
+            auto cameraState = getCameraState(cameraId);
+            if (cameraState != nullptr) {
+                if (!cameraState->getShimParams().isEmpty()) return NO_ERROR;
+            }
+        }
+
+        sp<BasicClient> clientTmp = nullptr;
+        std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
+        if ((ret = handleEvictionsLocked(cameraId, clientPid, effectiveApiLevel,
+                IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp,
+                /*out*/&partial)) != NO_ERROR) {
+            return ret;
+        }
+
+        if (clientTmp.get() != nullptr) {
+            // Handle special case for API1 MediaRecorder where the existing client is returned
+            device = static_cast<CLIENT*>(clientTmp.get());
+            return NO_ERROR;
+        }
+
+        // give flashlight a chance to close devices if necessary.
+        mFlashlight->prepareDeviceOpen(cameraId);
+
+        // TODO: Update getDeviceVersion + HAL interface to use strings for Camera IDs
+        int id = cameraIdToInt(cameraId);
+        if (id == -1) {
+            ALOGE("%s: Invalid camera ID %s, cannot get device version from HAL.", __FUNCTION__,
+                    cameraId.string());
+            return BAD_VALUE;
+        }
+
+        int facing = -1;
+        int deviceVersion = getDeviceVersion(id, /*out*/&facing);
+        sp<BasicClient> tmp = nullptr;
+        if((ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
+                clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
+                /*out*/&tmp)) != NO_ERROR) {
+            return ret;
+        }
+        client = static_cast<CLIENT*>(tmp.get());
+
+        LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
+                __FUNCTION__);
+
+        if ((ret = client->initialize(mModule)) != OK) {
+            ALOGE("%s: Could not initialize client from HAL module.", __FUNCTION__);
+            return ret;
+        }
+
+        sp<IBinder> remoteCallback = client->getRemote();
+        if (remoteCallback != nullptr) {
+            remoteCallback->linkToDeath(this);
+        }
+
+        // Update shim paremeters for legacy clients
+        if (effectiveApiLevel == API_1) {
+            // Assume we have always received a Client subclass for API1
+            sp<Client> shimClient = reinterpret_cast<Client*>(client.get());
+            String8 rawParams = shimClient->getParameters();
+            CameraParameters params(rawParams);
+
+            auto cameraState = getCameraState(cameraId);
+            if (cameraState != nullptr) {
+                cameraState->setShimParams(params);
+            } else {
+                ALOGE("%s: Cannot update shim parameters for camera %s, no such device exists.",
+                        __FUNCTION__, cameraId.string());
+            }
+        }
+
+        if (shimUpdateOnly) {
+            // If only updating legacy shim parameters, immediately disconnect client
+            mServiceLock.unlock();
+            client->disconnect();
+            mServiceLock.lock();
+        } else {
+            // Otherwise, add client to active clients list
+            finishConnectLocked(client, partial);
+        }
+    } // lock is destroyed, allow further connect calls
+
+    // Important: release the mutex here so the client can call back into the service from its
+    // destructor (can be at the end of the call)
+    device = client;
+    return NO_ERROR;
+}
+
 } // namespace android
 
 #endif
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index f3a88a1..6f44aee 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -67,7 +67,7 @@
     mLegacyMode = legacyMode;
 }
 
-status_t Camera2Client::initialize(camera_module_t *module)
+status_t Camera2Client::initialize(CameraModule *module)
 {
     ATRACE_CALL();
     ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
@@ -163,10 +163,9 @@
 
 status_t Camera2Client::dump(int fd, const Vector<String16>& args) {
     String8 result;
-    result.appendFormat("Client2[%d] (%p) Client: %s PID: %d, dump:\n",
-            mCameraId,
-            getRemoteCallback()->asBinder().get(),
-            String8(mClientPackageName).string(),
+    result.appendFormat("Client2[%d] (%p) PID: %d, dump:\n", mCameraId,
+            (getRemoteCallback() != NULL ?
+                    (IInterface::asBinder(getRemoteCallback()).get()) : NULL),
             mClientPid);
     result.append("  State: ");
 #define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
@@ -531,7 +530,7 @@
     sp<IBinder> binder;
     sp<ANativeWindow> window;
     if (bufferProducer != 0) {
-        binder = bufferProducer->asBinder();
+        binder = IInterface::asBinder(bufferProducer);
         // Using controlledByApp flag to ensure that the buffer queue remains in
         // async mode for the old camera API, where many applications depend
         // on that behavior.
@@ -917,6 +916,15 @@
                 ALOGE("%s: Camera %d: Can't stop streaming: %s (%d)",
                         __FUNCTION__, mCameraId, strerror(-res), res);
             }
+
+            // Flush all in-process captures and buffer in order to stop
+            // preview faster.
+            res = mDevice->flush();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Unable to flush pending requests: %s (%d)",
+                        __FUNCTION__, mCameraId, strerror(-res), res);
+            }
+
             res = mDevice->waitUntilDrained();
             if (res != OK) {
                 ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
@@ -929,13 +937,6 @@
                         "stop preview: %s (%d)",
                         __FUNCTION__, mCameraId, strerror(-res), res);
             }
-            {
-                // Ideally we should recover the override after recording stopped, but
-                // right now recording stream will live until here, so we are forced to
-                // recover here. TODO: find a better way to handle that (b/17495165)
-                SharedParameters::Lock l(mParameters);
-                l.mParameters.recoverOverriddenJpegSize();
-            }
             // no break
         case Parameters::WAITING_FOR_PREVIEW_WINDOW: {
             SharedParameters::Lock l(mParameters);
@@ -1206,6 +1207,28 @@
 
     mCameraService->playSound(CameraService::SOUND_RECORDING);
 
+    // Remove recording stream to prevent it from slowing down takePicture later
+    if (!l.mParameters.recordingHint && l.mParameters.isJpegSizeOverridden()) {
+        res = stopStream();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Can't stop streaming: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+        }
+        res = mDevice->waitUntilDrained();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+        }
+        // Clean up recording stream
+        res = mStreamingProcessor->deleteRecordingStream();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Unable to delete recording stream before "
+                    "stop preview: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+        }
+        l.mParameters.recoverOverriddenJpegSize();
+    }
+
     res = startPreviewL(l.mParameters, true);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to return to preview",
@@ -1388,6 +1411,34 @@
                     return res;
                 }
                 l.mParameters.state = Parameters::STILL_CAPTURE;
+
+                // Remove recording stream to prevent video snapshot jpeg logic kicking in
+                if (l.mParameters.isJpegSizeOverridden() &&
+                        mStreamingProcessor->getRecordingStreamId() != NO_STREAM) {
+                    res = mStreamingProcessor->togglePauseStream(/*pause*/true);
+                    if (res != OK) {
+                        ALOGE("%s: Camera %d: Can't pause streaming: %s (%d)",
+                                __FUNCTION__, mCameraId, strerror(-res), res);
+                    }
+                    res = mDevice->waitUntilDrained();
+                    if (res != OK) {
+                        ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
+                                __FUNCTION__, mCameraId, strerror(-res), res);
+                    }
+                    // Clean up recording stream
+                    res = mStreamingProcessor->deleteRecordingStream();
+                    if (res != OK) {
+                        ALOGE("%s: Camera %d: Unable to delete recording stream before "
+                                "stop preview: %s (%d)",
+                                __FUNCTION__, mCameraId, strerror(-res), res);
+                    }
+                    res = mStreamingProcessor->togglePauseStream(/*pause*/false);
+                    if (res != OK) {
+                        ALOGE("%s: Camera %d: Can't unpause streaming: %s (%d)",
+                                __FUNCTION__, mCameraId, strerror(-res), res);
+                    }
+                    l.mParameters.recoverOverriddenJpegSize();
+                }
                 break;
             case Parameters::RECORD:
                 // Good to go for video snapshot
@@ -1906,7 +1957,7 @@
             return width * height * 2;
         case HAL_PIXEL_FORMAT_RGBA_8888:
             return width * height * 4;
-        case HAL_PIXEL_FORMAT_RAW_SENSOR:
+        case HAL_PIXEL_FORMAT_RAW16:
             return width * height * 2;
         default:
             ALOGE("%s: Unknown preview format: %x",
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index d68bb29..5a8241f 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -94,7 +94,7 @@
 
     virtual ~Camera2Client();
 
-    status_t initialize(camera_module_t *module);
+    status_t initialize(CameraModule *module);
 
     virtual status_t dump(int fd, const Vector<String16>& args);
 
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 1a4d9a6..e552633 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -59,7 +59,7 @@
     LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
 }
 
-status_t CameraClient::initialize(camera_module_t *module) {
+status_t CameraClient::initialize(CameraModule *module) {
     int callingPid = getCallingPid();
     status_t res;
 
@@ -75,7 +75,7 @@
     snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
 
     mHardware = new CameraHardwareInterface(camera_device_name);
-    res = mHardware->initialize(&module->common);
+    res = mHardware->initialize(module);
     if (res != OK) {
         ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
                 __FUNCTION__, mCameraId, strerror(-res), res);
@@ -99,12 +99,7 @@
 
 // tear down the client
 CameraClient::~CameraClient() {
-    // this lock should never be NULL
-    Mutex* lock = mCameraService->getClientLockById(mCameraId);
-    lock->lock();
     mDestructionStarted = true;
-    // client will not be accessed from callback. should unlock to prevent dead-lock in disconnect
-    lock->unlock();
     int callingPid = getCallingPid();
     LOG1("CameraClient::~CameraClient E (pid %d, this %p)", callingPid, this);
 
@@ -116,10 +111,11 @@
     const size_t SIZE = 256;
     char buffer[SIZE];
 
-    size_t len = snprintf(buffer, SIZE, "Client[%d] (%p) PID: %d\n",
+    size_t len = snprintf(buffer, SIZE, "Client[%d] (%p) with UID %d\n",
             mCameraId,
-            getRemoteCallback()->asBinder().get(),
-            mClientPid);
+            (getRemoteCallback() != NULL ?
+                    IInterface::asBinder(getRemoteCallback()).get() : NULL),
+            mClientUid);
     len = (len > SIZE - 1) ? SIZE - 1 : len;
     write(fd, buffer, len);
 
@@ -205,7 +201,7 @@
     }
 
     if (mRemoteCallback != 0 &&
-        (client->asBinder() == mRemoteCallback->asBinder())) {
+        (IInterface::asBinder(client) == IInterface::asBinder(mRemoteCallback))) {
         LOG1("Connect to the same client");
         return NO_ERROR;
     }
@@ -328,7 +324,7 @@
     sp<IBinder> binder;
     sp<ANativeWindow> window;
     if (bufferProducer != 0) {
-        binder = bufferProducer->asBinder();
+        binder = IInterface::asBinder(bufferProducer);
         // Using controlledByApp flag to ensure that the buffer queue remains in
         // async mode for the old camera API, where many applications depend
         // on that behavior.
@@ -676,6 +672,13 @@
                 LOG1("lockIfMessageWanted(%d): waited for %d ms",
                     msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
             }
+
+            // If messages are no longer enabled after acquiring lock, release and drop message
+            if ((mMsgEnabled & msgType) == 0) {
+                mLock.unlock();
+                break;
+            }
+
             return true;
         }
         if (sleepCount++ == 0) {
@@ -701,26 +704,13 @@
 //      (others)                        c->dataCallback
 // dataCallbackTimestamp
 //      (others)                        c->dataCallbackTimestamp
-//
-// NOTE: the *Callback functions grab mLock of the client before passing
-// control to handle* functions. So the handle* functions must release the
-// lock before calling the ICameraClient's callbacks, so those callbacks can
-// invoke methods in the Client class again (For example, the preview frame
-// callback may want to releaseRecordingFrame). The handle* functions must
-// release the lock after all accesses to member variables, so it must be
-// handled very carefully.
 
 void CameraClient::notifyCallback(int32_t msgType, int32_t ext1,
         int32_t ext2, void* user) {
     LOG2("notifyCallback(%d)", msgType);
 
-    Mutex* lock = getClientLockFromCookie(user);
-    if (lock == NULL) return;
-    Mutex::Autolock alock(*lock);
-
-    CameraClient* client =
-            static_cast<CameraClient*>(getClientFromCookie(user));
-    if (client == NULL) return;
+    sp<CameraClient> client = static_cast<CameraClient*>(getClientFromCookie(user).get());
+    if (client.get() == nullptr) return;
 
     if (!client->lockIfMessageWanted(msgType)) return;
 
@@ -739,13 +729,8 @@
         const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
     LOG2("dataCallback(%d)", msgType);
 
-    Mutex* lock = getClientLockFromCookie(user);
-    if (lock == NULL) return;
-    Mutex::Autolock alock(*lock);
-
-    CameraClient* client =
-            static_cast<CameraClient*>(getClientFromCookie(user));
-    if (client == NULL) return;
+    sp<CameraClient> client = static_cast<CameraClient*>(getClientFromCookie(user).get());
+    if (client.get() == nullptr) return;
 
     if (!client->lockIfMessageWanted(msgType)) return;
     if (dataPtr == 0 && metadata == NULL) {
@@ -777,13 +762,8 @@
         int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
     LOG2("dataCallbackTimestamp(%d)", msgType);
 
-    Mutex* lock = getClientLockFromCookie(user);
-    if (lock == NULL) return;
-    Mutex::Autolock alock(*lock);
-
-    CameraClient* client =
-            static_cast<CameraClient*>(getClientFromCookie(user));
-    if (client == NULL) return;
+    sp<CameraClient> client = static_cast<CameraClient*>(getClientFromCookie(user).get());
+    if (client.get() == nullptr) return;
 
     if (!client->lockIfMessageWanted(msgType)) return;
 
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 63a9d0f..95616b2 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -68,7 +68,7 @@
             bool legacyMode = false);
     ~CameraClient();
 
-    status_t initialize(camera_module_t *module);
+    status_t initialize(CameraModule *module);
 
     status_t dump(int fd, const Vector<String16>& args);
 
diff --git a/services/camera/libcameraservice/api1/client2/BurstCapture.cpp b/services/camera/libcameraservice/api1/client2/BurstCapture.cpp
index 0bfdfd4..5502dcb 100644
--- a/services/camera/libcameraservice/api1/client2/BurstCapture.cpp
+++ b/services/camera/libcameraservice/api1/client2/BurstCapture.cpp
@@ -44,7 +44,7 @@
     return INVALID_OPERATION;
 }
 
-void BurstCapture::onFrameAvailable() {
+void BurstCapture::onFrameAvailable(const BufferItem &/*item*/) {
     ALOGV("%s", __FUNCTION__);
     Mutex::Autolock l(mInputMutex);
     if(!mInputChanged) {
diff --git a/services/camera/libcameraservice/api1/client2/BurstCapture.h b/services/camera/libcameraservice/api1/client2/BurstCapture.h
index ea321fd..c3b7722 100644
--- a/services/camera/libcameraservice/api1/client2/BurstCapture.h
+++ b/services/camera/libcameraservice/api1/client2/BurstCapture.h
@@ -39,7 +39,7 @@
     BurstCapture(wp<Camera2Client> client, wp<CaptureSequencer> sequencer);
     virtual ~BurstCapture();
 
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
     virtual status_t start(Vector<CameraMetadata> &metadatas, int32_t firstCaptureId);
 
 protected:
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index bf3318e..5c8f750 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -46,7 +46,7 @@
     deleteStream();
 }
 
-void CallbackProcessor::onFrameAvailable() {
+void CallbackProcessor::onFrameAvailable(const BufferItem& /*item*/) {
     Mutex::Autolock l(mInputMutex);
     if (!mCallbackAvailable) {
         mCallbackAvailable = true;
@@ -154,8 +154,8 @@
                 params.previewWidth, params.previewHeight,
                 callbackFormat, params.previewFormat);
         res = device->createStream(mCallbackWindow,
-                params.previewWidth, params.previewHeight,
-                callbackFormat, &mCallbackStreamId);
+                params.previewWidth, params.previewHeight, callbackFormat,
+                HAL_DATASPACE_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.h b/services/camera/libcameraservice/api1/client2/CallbackProcessor.h
index 613f5be..7fdc329 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.h
@@ -44,7 +44,7 @@
     CallbackProcessor(sp<Camera2Client> client);
     ~CallbackProcessor();
 
-    void onFrameAvailable();
+    void onFrameAvailable(const BufferItem& item);
 
     // Set to NULL to disable the direct-to-app callback window
     status_t setCallbackWindow(sp<ANativeWindow> callbackWindow);
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
index 312a78c..40d53b3 100644
--- a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
@@ -168,6 +168,19 @@
             faceIds = entry.data.i32;
         }
 
+        entry = frame.find(ANDROID_SCALER_CROP_REGION);
+        if (entry.count < 4) {
+            ALOGE("%s: Camera %d: Unable to read crop region (count = %d)",
+                    __FUNCTION__, client->getCameraId(), entry.count);
+            return res;
+        }
+
+        Parameters::CropRegion scalerCrop = {
+            static_cast<float>(entry.data.i32[0]),
+            static_cast<float>(entry.data.i32[1]),
+            static_cast<float>(entry.data.i32[2]),
+            static_cast<float>(entry.data.i32[3])};
+
         faces.setCapacity(metadata.number_of_faces);
 
         size_t maxFaces = metadata.number_of_faces;
@@ -183,26 +196,30 @@
 
             camera_face_t face;
 
-            face.rect[0] = l.mParameters.arrayXToNormalized(faceRects[i*4 + 0]);
-            face.rect[1] = l.mParameters.arrayYToNormalized(faceRects[i*4 + 1]);
-            face.rect[2] = l.mParameters.arrayXToNormalized(faceRects[i*4 + 2]);
-            face.rect[3] = l.mParameters.arrayYToNormalized(faceRects[i*4 + 3]);
+            face.rect[0] = l.mParameters.arrayXToNormalizedWithCrop(
+                                faceRects[i*4 + 0], scalerCrop);
+            face.rect[1] = l.mParameters.arrayYToNormalizedWithCrop(
+                                faceRects[i*4 + 1], scalerCrop);
+            face.rect[2] = l.mParameters.arrayXToNormalizedWithCrop(
+                                faceRects[i*4 + 2], scalerCrop);
+            face.rect[3] = l.mParameters.arrayYToNormalizedWithCrop(
+                                faceRects[i*4 + 3], scalerCrop);
 
             face.score = faceScores[i];
             if (faceDetectMode == ANDROID_STATISTICS_FACE_DETECT_MODE_FULL) {
                 face.id = faceIds[i];
-                face.left_eye[0] =
-                    l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 0]);
-                face.left_eye[1] =
-                    l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 1]);
-                face.right_eye[0] =
-                    l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 2]);
-                face.right_eye[1] =
-                    l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 3]);
-                face.mouth[0] =
-                    l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 4]);
-                face.mouth[1] =
-                    l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 5]);
+                face.left_eye[0] = l.mParameters.arrayXToNormalizedWithCrop(
+                        faceLandmarks[i*6 + 0], scalerCrop);
+                face.left_eye[1] = l.mParameters.arrayYToNormalizedWithCrop(
+                        faceLandmarks[i*6 + 1], scalerCrop);
+                face.right_eye[0] = l.mParameters.arrayXToNormalizedWithCrop(
+                        faceLandmarks[i*6 + 2], scalerCrop);
+                face.right_eye[1] = l.mParameters.arrayYToNormalizedWithCrop(
+                        faceLandmarks[i*6 + 3], scalerCrop);
+                face.mouth[0] = l.mParameters.arrayXToNormalizedWithCrop(
+                        faceLandmarks[i*6 + 4], scalerCrop);
+                face.mouth[1] = l.mParameters.arrayYToNormalizedWithCrop(
+                        faceLandmarks[i*6 + 5], scalerCrop);
             } else {
                 face.id = 0;
                 face.left_eye[0] = face.left_eye[1] = -2000;
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index b433781..34798bf 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -51,7 +51,7 @@
     deleteStream();
 }
 
-void JpegProcessor::onFrameAvailable() {
+void JpegProcessor::onFrameAvailable(const BufferItem& /*item*/) {
     Mutex::Autolock l(mInputMutex);
     if (!mCaptureAvailable) {
         mCaptureAvailable = true;
@@ -145,7 +145,8 @@
         // Create stream for HAL production
         res = device->createStream(mCaptureWindow,
                 params.pictureWidth, params.pictureHeight,
-                HAL_PIXEL_FORMAT_BLOB, &mCaptureStreamId);
+                HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_JFIF,
+                CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for capture: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.h b/services/camera/libcameraservice/api1/client2/JpegProcessor.h
index b2c05df..2040b30 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.h
@@ -47,7 +47,7 @@
     ~JpegProcessor();
 
     // CpuConsumer listener implementation
-    void onFrameAvailable();
+    void onFrameAvailable(const BufferItem& item);
 
     status_t updateStream(const Parameters &params);
     status_t deleteStream();
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 42a5507..87e0132 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -182,9 +182,9 @@
                 supportedPreviewFormats +=
                     CameraParameters::PIXEL_FORMAT_YUV420SP;
                 break;
-            // Not advertizing JPEG, RAW_SENSOR, etc, for preview formats
+            // Not advertizing JPEG, RAW16, etc, for preview formats
             case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
-            case HAL_PIXEL_FORMAT_RAW_SENSOR:
+            case HAL_PIXEL_FORMAT_RAW16:
             case HAL_PIXEL_FORMAT_BLOB:
                 addComma = false;
                 break;
@@ -596,6 +596,10 @@
                     supportedSceneModes +=
                         CameraParameters::SCENE_MODE_BARCODE;
                     break;
+                case ANDROID_CONTROL_SCENE_MODE_HDR:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_HDR;
+                    break;
                 default:
                     ALOGW("%s: Camera %d: Unknown scene mode value: %d",
                         __FUNCTION__, cameraId,
@@ -2203,6 +2207,10 @@
     return OK;
 }
 
+bool Parameters::isJpegSizeOverridden() {
+    return pictureSizeOverriden;
+}
+
 const char* Parameters::getStateName(State state) {
 #define CASE_ENUM_TO_CHAR(x) case x: return(#x); break;
     switch(state) {
@@ -2245,7 +2253,7 @@
         case HAL_PIXEL_FORMAT_RGBA_8888:   // RGBA8888
             fmt = CameraParameters::PIXEL_FORMAT_RGBA8888;
             break;
-        case HAL_PIXEL_FORMAT_RAW_SENSOR:
+        case HAL_PIXEL_FORMAT_RAW16:
             ALOGW("Raw sensor preview format requested.");
             fmt = CameraParameters::PIXEL_FORMAT_BAYER_RGGB;
             break;
@@ -2382,6 +2390,8 @@
             ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT :
         !strcmp(sceneMode, CameraParameters::SCENE_MODE_BARCODE) ?
             ANDROID_CONTROL_SCENE_MODE_BARCODE:
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_HDR) ?
+            ANDROID_CONTROL_SCENE_MODE_HDR:
         -1;
 }
 
@@ -2619,58 +2629,6 @@
     return (y + 1000) * (previewCrop.height - 1) / 2000;
 }
 
-int Parameters::arrayXToCrop(int x) const {
-    CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
-    return x - previewCrop.left;
-}
-
-int Parameters::arrayYToCrop(int y) const {
-    CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
-    return y - previewCrop.top;
-}
-
-int Parameters::cropXToNormalized(int x) const {
-    CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
-    return x * 2000 / (previewCrop.width - 1) - 1000;
-}
-
-int Parameters::cropYToNormalized(int y) const {
-    CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
-    return y * 2000 / (previewCrop.height - 1) - 1000;
-}
-
-int Parameters::arrayXToNormalized(int width) const {
-    int ret = cropXToNormalized(arrayXToCrop(width));
-
-    ALOG_ASSERT(ret >= -1000, "Calculated normalized value out of "
-        "lower bounds %d", ret);
-    ALOG_ASSERT(ret <= 1000, "Calculated normalized value out of "
-        "upper bounds %d", ret);
-
-    // Work-around for HAL pre-scaling the coordinates themselves
-    if (quirks.meteringCropRegion) {
-        return width * 2000 / (fastInfo.arrayWidth - 1) - 1000;
-    }
-
-    return ret;
-}
-
-int Parameters::arrayYToNormalized(int height) const {
-    int ret = cropYToNormalized(arrayYToCrop(height));
-
-    ALOG_ASSERT(ret >= -1000, "Calculated normalized value out of lower bounds"
-        " %d", ret);
-    ALOG_ASSERT(ret <= 1000, "Calculated normalized value out of upper bounds"
-        " %d", ret);
-
-    // Work-around for HAL pre-scaling the coordinates themselves
-    if (quirks.meteringCropRegion) {
-        return height * 2000 / (fastInfo.arrayHeight - 1) - 1000;
-    }
-
-    return ret;
-}
-
 int Parameters::normalizedXToArray(int x) const {
 
     // Work-around for HAL pre-scaling the coordinates themselves
@@ -2690,6 +2648,54 @@
     return cropYToArray(normalizedYToCrop(y));
 }
 
+
+Parameters::CropRegion Parameters::calculatePreviewCrop(
+        const CropRegion &scalerCrop) const {
+    float left, top, width, height;
+    float previewAspect = static_cast<float>(previewWidth) / previewHeight;
+    float cropAspect = scalerCrop.width / scalerCrop.height;
+
+    if (previewAspect > cropAspect) {
+        width = scalerCrop.width;
+        height = cropAspect * scalerCrop.height / previewAspect;
+
+        left = scalerCrop.left;
+        top = scalerCrop.top + (scalerCrop.height - height) / 2;
+    } else {
+        width = previewAspect * scalerCrop.width / cropAspect;
+        height = scalerCrop.height;
+
+        left = scalerCrop.left + (scalerCrop.width - width) / 2;
+        top = scalerCrop.top;
+    }
+
+    CropRegion previewCrop = {left, top, width, height};
+
+    return previewCrop;
+}
+
+int Parameters::arrayXToNormalizedWithCrop(int x,
+        const CropRegion &scalerCrop) const {
+    // Work-around for HAL pre-scaling the coordinates themselves
+    if (quirks.meteringCropRegion) {
+        return x * 2000 / (fastInfo.arrayWidth - 1) - 1000;
+    } else {
+        CropRegion previewCrop = calculatePreviewCrop(scalerCrop);
+        return (x - previewCrop.left) * 2000 / (previewCrop.width - 1) - 1000;
+    }
+}
+
+int Parameters::arrayYToNormalizedWithCrop(int y,
+        const CropRegion &scalerCrop) const {
+    // Work-around for HAL pre-scaling the coordinates themselves
+    if (quirks.meteringCropRegion) {
+        return y * 2000 / (fastInfo.arrayHeight - 1) - 1000;
+    } else {
+        CropRegion previewCrop = calculatePreviewCrop(scalerCrop);
+        return (y - previewCrop.top) * 2000 / (previewCrop.height - 1) - 1000;
+    }
+}
+
 status_t Parameters::getFilteredSizes(Size limit, Vector<Size> *sizes) {
     if (info == NULL) {
         ALOGE("%s: Static metadata is not initialized", __FUNCTION__);
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index 815cc55..e628a7e 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -19,11 +19,13 @@
 
 #include <system/graphics.h>
 
+#include <utils/Compat.h>
 #include <utils/Errors.h>
+#include <utils/KeyedVector.h>
 #include <utils/Mutex.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
-#include <utils/KeyedVector.h>
+
 #include <camera/CameraParameters.h>
 #include <camera/CameraParameters2.h>
 #include <camera/CameraMetadata.h>
@@ -187,7 +189,7 @@
     static const int MAX_INITIAL_PREVIEW_WIDTH = 1920;
     static const int MAX_INITIAL_PREVIEW_HEIGHT = 1080;
     // Aspect ratio tolerance
-    static const float ASPECT_RATIO_TOLERANCE = 0.001;
+    static const CONSTEXPR float ASPECT_RATIO_TOLERANCE = 0.001;
 
     // Full static camera info, object owned by someone else, such as
     // Camera2Device.
@@ -266,6 +268,8 @@
     status_t overrideJpegSizeByVideoSize();
     // Recover overridden jpeg size.  Called during stopRecording.
     status_t recoverOverriddenJpegSize();
+    // if video snapshot size is currently overridden
+    bool isJpegSizeOverridden();
 
     // Calculate the crop region rectangle based on current stream sizes
     struct CropRegion {
@@ -325,13 +329,17 @@
     // Note that this doesn't apply to the (deprecated) single FPS value.
     static const int kFpsToApiScale = 1000;
 
-    // Transform between (-1000,-1000)-(1000,1000) normalized coords from camera
-    // API and HAL2 (0,0)-(activePixelArray.width/height) coordinates
-    int arrayXToNormalized(int width) const;
-    int arrayYToNormalized(int height) const;
+    // Transform from (-1000,-1000)-(1000,1000) normalized coords from camera
+    // API to HAL2 (0,0)-(activePixelArray.width/height) coordinates
     int normalizedXToArray(int x) const;
     int normalizedYToArray(int y) const;
 
+    // Transform from HAL3 (0,0)-(activePixelArray.width/height) coordinates to
+    // (-1000,-1000)-(1000,1000) normalized coordinates given a scaler crop
+    // region.
+    int arrayXToNormalizedWithCrop(int x, const CropRegion &scalerCrop) const;
+    int arrayYToNormalizedWithCrop(int y, const CropRegion &scalerCrop) const;
+
     struct Range {
         int min;
         int max;
@@ -341,20 +349,20 @@
 
 private:
 
-    // Convert between HAL2 sensor array coordinates and
-    // viewfinder crop-region relative array coordinates
+    // Convert from viewfinder crop-region relative array coordinates
+    // to HAL2 sensor array coordinates
     int cropXToArray(int x) const;
     int cropYToArray(int y) const;
-    int arrayXToCrop(int x) const;
-    int arrayYToCrop(int y) const;
 
-    // Convert between viewfinder crop-region relative array coordinates
-    // and camera API (-1000,1000)-(1000,1000) normalized coords
-    int cropXToNormalized(int x) const;
-    int cropYToNormalized(int y) const;
+    // Convert from camera API (-1000,1000)-(1000,1000) normalized coords
+    // to viewfinder crop-region relative array coordinates
     int normalizedXToCrop(int x) const;
     int normalizedYToCrop(int y) const;
 
+    // Given a scaler crop region, calculate preview crop region based on
+    // preview aspect ratio.
+    CropRegion calculatePreviewCrop(const CropRegion &scalerCrop) const;
+
     Vector<Size> availablePreviewSizes;
     Vector<Size> availableVideoSizes;
     // Get size list (that are no larger than limit) from static metadata.
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 9e7fff8..b6071f6 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -27,6 +27,7 @@
 
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <gui/BufferItem.h>
 #include <gui/Surface.h>
 #include <media/hardware/MetadataBufferType.h>
 
@@ -181,7 +182,8 @@
     if (mPreviewStreamId == NO_STREAM) {
         res = device->createStream(mPreviewWindow,
                 params.previewWidth, params.previewHeight,
-                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mPreviewStreamId);
+                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_UNKNOWN,
+                CAMERA3_STREAM_ROTATION_0, &mPreviewStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
                     __FUNCTION__, mId, strerror(-res), res);
@@ -420,9 +422,12 @@
 
     if (mRecordingStreamId == NO_STREAM) {
         mRecordingFrameCount = 0;
+        // Selecting BT.709 colorspace by default
+        // TODO: Wire this in from encoder side
         res = device->createStream(mRecordingWindow,
                 params.videoWidth, params.videoHeight,
-                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, &mRecordingStreamId);
+                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_BT709,
+                CAMERA3_STREAM_ROTATION_0, &mRecordingStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for recording: "
                     "%s (%d)", __FUNCTION__, mId,
@@ -635,7 +640,7 @@
     return OK;
 }
 
-void StreamingProcessor::onFrameAvailable() {
+void StreamingProcessor::onFrameAvailable(const BufferItem& /*item*/) {
     ATRACE_CALL();
     Mutex::Autolock l(mMutex);
     if (!mRecordingFrameAvailable) {
@@ -675,7 +680,7 @@
     sp<Camera2Client> client = mClient.promote();
     if (client == 0) {
         // Discard frames during shutdown
-        BufferItemConsumer::BufferItem imgBuffer;
+        BufferItem imgBuffer;
         res = mRecordingConsumer->acquireBuffer(&imgBuffer, 0);
         if (res != OK) {
             if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
@@ -693,7 +698,7 @@
             with Camera2Client code calling into StreamingProcessor */
         SharedParameters::Lock l(client->getParameters());
         Mutex::Autolock m(mMutex);
-        BufferItemConsumer::BufferItem imgBuffer;
+        BufferItem imgBuffer;
         res = mRecordingConsumer->acquireBuffer(&imgBuffer, 0);
         if (res != OK) {
             if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
@@ -819,8 +824,7 @@
 
     size_t itemIndex;
     for (itemIndex = 0; itemIndex < mRecordingBuffers.size(); itemIndex++) {
-        const BufferItemConsumer::BufferItem item =
-                mRecordingBuffers[itemIndex];
+        const BufferItem item = mRecordingBuffers[itemIndex];
         if (item.mBuf != BufferItemConsumer::INVALID_BUFFER_SLOT &&
                 item.mGraphicBuffer->handle == imgHandle) {
             break;
@@ -864,8 +868,7 @@
 
     size_t releasedCount = 0;
     for (size_t itemIndex = 0; itemIndex < mRecordingBuffers.size(); itemIndex++) {
-        const BufferItemConsumer::BufferItem item =
-                mRecordingBuffers[itemIndex];
+        const BufferItem item = mRecordingBuffers[itemIndex];
         if (item.mBuf != BufferItemConsumer::INVALID_BUFFER_SLOT) {
             res = mRecordingConsumer->releaseBuffer(mRecordingBuffers[itemIndex]);
             if (res != OK) {
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.h b/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
index 8466af4..2474062 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
@@ -80,7 +80,7 @@
     status_t incrementStreamingIds();
 
     // Callback for new recording frames from HAL
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
     // Callback from stagefright which returns used recording frames
     void releaseRecordingFrame(const sp<IMemory>& mem);
 
@@ -124,7 +124,7 @@
 
     static const size_t kDefaultRecordingHeapCount = 8;
     size_t mRecordingHeapCount;
-    Vector<BufferItemConsumer::BufferItem> mRecordingBuffers;
+    Vector<BufferItem> mRecordingBuffers;
     size_t mRecordingHeapHead, mRecordingHeapFree;
 
     virtual bool threadLoop();
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 8f78103..a03f9c7 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -66,7 +66,7 @@
     disconnect();
 }
 
-void ZslProcessor::onFrameAvailable() {
+void ZslProcessor::onFrameAvailable(const BufferItem& /*item*/) {
     Mutex::Autolock l(mInputMutex);
     if (!mZslBufferAvailable) {
         mZslBufferAvailable = true;
@@ -185,8 +185,8 @@
                 (int)CAMERA2_HAL_PIXEL_FORMAT_ZSL :
                 (int)HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
         res = device->createStream(mZslWindow,
-                params.fastInfo.arrayWidth, params.fastInfo.arrayHeight,
-                streamType, &mZslStreamId);
+                params.fastInfo.arrayWidth, params.fastInfo.arrayHeight, streamType,
+                HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mZslStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for ZSL: "
                     "%s (%d)", __FUNCTION__, mId,
@@ -440,7 +440,7 @@
         zslConsumer = mZslConsumer;
     }
     ALOGVV("Trying to get next buffer");
-    BufferItemConsumer::BufferItem item;
+    BufferItem item;
     res = zslConsumer->acquireBuffer(&item, 0);
     if (res != OK) {
         if (res != BufferItemConsumer::NO_BUFFER_AVAILABLE) {
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.h b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
index b6533cf..5f50d7b 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.h
@@ -22,6 +22,7 @@
 #include <utils/Vector.h>
 #include <utils/Mutex.h>
 #include <utils/Condition.h>
+#include <gui/BufferItem.h>
 #include <gui/BufferItemConsumer.h>
 #include <camera/CameraMetadata.h>
 #include <camera/CaptureResult.h>
@@ -53,7 +54,7 @@
     ~ZslProcessor();
 
     // From mZslConsumer
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
     // From FrameProcessor
     virtual void onResultAvailable(const CaptureResult &result);
 
@@ -103,7 +104,7 @@
     sp<ANativeWindow>      mZslWindow;
 
     struct ZslPair {
-        BufferItemConsumer::BufferItem buffer;
+        BufferItem buffer;
         CameraMetadata frame;
     };
 
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp
index f110b66..470a6d6 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp
@@ -592,7 +592,7 @@
                     if (afState != ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED &&
                             afState != ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED &&
                             afState != ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
-                        ALOGW("%s: ZSL queue frame AF state is %d is not good for capture, skip it",
+                        ALOGVV("%s: ZSL queue frame AF state is %d is not good for capture, skip it",
                                 __FUNCTION__, afState);
                         continue;
                     }
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor3.h b/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
index fc9f70c..2960478 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
@@ -22,6 +22,7 @@
 #include <utils/Vector.h>
 #include <utils/Mutex.h>
 #include <utils/Condition.h>
+#include <gui/BufferItem.h>
 #include <gui/BufferItemConsumer.h>
 #include <camera/CameraMetadata.h>
 
@@ -104,7 +105,7 @@
     sp<camera3::Camera3ZslStream> mZslStream;
 
     struct ZslPair {
-        BufferItemConsumer::BufferItem buffer;
+        BufferItem buffer;
         CameraMetadata frame;
     };
 
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index e3301aa..0e2311c 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -42,8 +42,14 @@
         int clientPid,
         uid_t clientUid,
         int servicePid) :
-    BasicClient(cameraService, remoteCallback->asBinder(), clientPackageName,
-                cameraId, cameraFacing, clientPid, clientUid, servicePid),
+    BasicClient(cameraService,
+            IInterface::asBinder(remoteCallback),
+            clientPackageName,
+            cameraId,
+            cameraFacing,
+            clientPid,
+            clientUid,
+            servicePid),
     mRemoteCallback(remoteCallback) {
 }
 
@@ -65,7 +71,7 @@
     ALOGI("CameraDeviceClient %d: Opened", cameraId);
 }
 
-status_t CameraDeviceClient::initialize(camera_module_t *module)
+status_t CameraDeviceClient::initialize(CameraModule *module)
 {
     ATRACE_CALL();
     status_t res;
@@ -157,7 +163,7 @@
             if (surface == 0) continue;
 
             sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
-            int idx = mStreamMap.indexOfKey(gbp->asBinder());
+            int idx = mStreamMap.indexOfKey(IInterface::asBinder(gbp));
 
             // Trying to submit request with surface that wasn't created
             if (idx == NAME_NOT_FOUND) {
@@ -308,17 +314,17 @@
     return res;
 }
 
-status_t CameraDeviceClient::createStream(int width, int height, int format,
-                      const sp<IGraphicBufferProducer>& bufferProducer)
+status_t CameraDeviceClient::createStream(const OutputConfiguration &outputConfiguration)
 {
     ATRACE_CALL();
-    ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
 
     status_t res;
     if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
 
     Mutex::Autolock icl(mBinderSerializationLock);
 
+
+    sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer();
     if (bufferProducer == NULL) {
         ALOGE("%s: bufferProducer must not be null", __FUNCTION__);
         return BAD_VALUE;
@@ -327,7 +333,7 @@
 
     // Don't create multiple streams for the same target surface
     {
-        ssize_t index = mStreamMap.indexOfKey(bufferProducer->asBinder());
+        ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
         if (index != NAME_NOT_FOUND) {
             ALOGW("%s: Camera %d: Buffer producer already has a stream for it "
                   "(ID %zd)",
@@ -353,14 +359,19 @@
         useAsync = true;
     }
 
-    sp<IBinder> binder;
-    sp<ANativeWindow> anw;
-    if (bufferProducer != 0) {
-        binder = bufferProducer->asBinder();
-        anw = new Surface(bufferProducer, useAsync);
-    }
+    int32_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER |
+                              GRALLOC_USAGE_RENDERSCRIPT;
+    int32_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK |
+                           GraphicBuffer::USAGE_HW_TEXTURE |
+                           GraphicBuffer::USAGE_HW_COMPOSER;
+    bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 &&
+            (consumerUsage & allowedFlags) != 0;
 
-    // TODO: remove w,h,f since we are ignoring them
+    sp<IBinder> binder = IInterface::asBinder(bufferProducer);
+    sp<ANativeWindow> anw = new Surface(bufferProducer, useAsync);
+
+    int width, height, format;
+    android_dataspace dataSpace;
 
     if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
         ALOGE("%s: Camera %d: Failed to query Surface width", __FUNCTION__,
@@ -377,25 +388,38 @@
               mCameraId);
         return res;
     }
+    if ((res = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE,
+                            reinterpret_cast<int*>(&dataSpace))) != OK) {
+        ALOGE("%s: Camera %d: Failed to query Surface dataSpace", __FUNCTION__,
+              mCameraId);
+        return res;
+    }
 
     // FIXME: remove this override since the default format should be
     //       IMPLEMENTATION_DEFINED. b/9487482
     if (format >= HAL_PIXEL_FORMAT_RGBA_8888 &&
         format <= HAL_PIXEL_FORMAT_BGRA_8888) {
-        ALOGW("%s: Camera %d: Overriding format 0x%x to IMPLEMENTATION_DEFINED",
+        ALOGW("%s: Camera %d: Overriding format %#x to IMPLEMENTATION_DEFINED",
               __FUNCTION__, mCameraId, format);
         format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
     }
 
-    // TODO: add startConfigure/stopConfigure call to CameraDeviceBase
-    // this will make it so Camera3Device doesn't call configure_streams
-    // after each call, but only once we are done with all.
+    // Round dimensions to the nearest dimensions available for this format
+    if (flexibleConsumer && !CameraDeviceClient::roundBufferDimensionNearest(width, height,
+            format, dataSpace, mDevice->info(), /*out*/&width, /*out*/&height)) {
+        ALOGE("%s: No stream configurations with the format %#x defined, failed to create stream.",
+                __FUNCTION__, format);
+        return BAD_VALUE;
+    }
 
     int streamId = -1;
-    res = mDevice->createStream(anw, width, height, format, &streamId);
+    res = mDevice->createStream(anw, width, height, format, dataSpace,
+                                static_cast<camera3_stream_rotation_t>
+                                        (outputConfiguration.getRotation()),
+                                &streamId);
 
     if (res == OK) {
-        mStreamMap.add(bufferProducer->asBinder(), streamId);
+        mStreamMap.add(binder, streamId);
 
         ALOGV("%s: Camera %d: Successfully created a new stream ID %d",
               __FUNCTION__, mCameraId, streamId);
@@ -425,6 +449,64 @@
     return res;
 }
 
+
+bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
+        int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
+        /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
+
+    camera_metadata_ro_entry streamConfigs =
+            (dataSpace == HAL_DATASPACE_DEPTH) ?
+            info.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS) :
+            info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+
+    int32_t bestWidth = -1;
+    int32_t bestHeight = -1;
+
+    // Iterate through listed stream configurations and find the one with the smallest euclidean
+    // distance from the given dimensions for the given format.
+    for (size_t i = 0; i < streamConfigs.count; i += 4) {
+        int32_t fmt = streamConfigs.data.i32[i];
+        int32_t w = streamConfigs.data.i32[i + 1];
+        int32_t h = streamConfigs.data.i32[i + 2];
+
+        // Ignore input/output type for now
+        if (fmt == format) {
+            if (w == width && h == height) {
+                bestWidth = width;
+                bestHeight = height;
+                break;
+            } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 ||
+                    CameraDeviceClient::euclidDistSquare(w, h, width, height) <
+                    CameraDeviceClient::euclidDistSquare(bestWidth, bestHeight, width, height))) {
+                bestWidth = w;
+                bestHeight = h;
+            }
+        }
+    }
+
+    if (bestWidth == -1) {
+        // Return false if no configurations for this format were listed
+        return false;
+    }
+
+    // Set the outputs to the closet width/height
+    if (outWidth != NULL) {
+        *outWidth = bestWidth;
+    }
+    if (outHeight != NULL) {
+        *outHeight = bestHeight;
+    }
+
+    // Return true if at least one configuration for this format was listed
+    return true;
+}
+
+int64_t CameraDeviceClient::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) {
+    int64_t d0 = x0 - x1;
+    int64_t d1 = y0 - y1;
+    return d0 * d0 + d1 * d1;
+}
+
 // Create a request object from a template.
 status_t CameraDeviceClient::createDefaultRequest(int templateId,
                                                   /*out*/
@@ -514,10 +596,9 @@
     String8 result;
     result.appendFormat("CameraDeviceClient[%d] (%p) dump:\n",
             mCameraId,
-            getRemoteCallback()->asBinder().get());
-    result.appendFormat("  Current client: %s (PID %d, UID %u)\n",
-            String8(mClientPackageName).string(),
-            mClientPid, mClientUid);
+            (getRemoteCallback() != NULL ?
+                    IInterface::asBinder(getRemoteCallback()).get() : NULL) );
+    result.appendFormat("  Current client UID %u\n", mClientUid);
 
     result.append("  State:\n");
     result.appendFormat("    Request ID counter: %d\n", mRequestIdCounter);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 9981dfe..a3dbb90 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -19,6 +19,7 @@
 
 #include <camera/camera2/ICameraDeviceUser.h>
 #include <camera/camera2/ICameraDeviceCallbacks.h>
+#include <camera/camera2/OutputConfiguration.h>
 
 #include "CameraService.h"
 #include "common/FrameProcessorBase.h"
@@ -83,11 +84,7 @@
     // Returns -EBUSY if device is not idle
     virtual status_t      deleteStream(int streamId);
 
-    virtual status_t      createStream(
-            int width,
-            int height,
-            int format,
-            const sp<IGraphicBufferProducer>& bufferProducer);
+    virtual status_t      createStream(const OutputConfiguration &outputConfiguration);
 
     // Create a request object from a template.
     virtual status_t      createDefaultRequest(int templateId,
@@ -119,7 +116,7 @@
             int servicePid);
     virtual ~CameraDeviceClient();
 
-    virtual status_t      initialize(camera_module_t *module);
+    virtual status_t      initialize(CameraModule *module);
 
     virtual status_t      dump(int fd, const Vector<String16>& args);
 
@@ -154,6 +151,16 @@
     /** Utility members */
     bool enforceRequestPermissions(CameraMetadata& metadata);
 
+    // Find the square of the euclidean distance between two points
+    static int64_t euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1);
+
+    // Find the closest dimensions for a given format in available stream configurations with
+    // a width <= ROUNDING_WIDTH_CAP
+    static const int32_t ROUNDING_WIDTH_CAP = 1080;
+    static bool roundBufferDimensionNearest(int32_t width, int32_t height, int32_t format,
+            android_dataspace dataSpace, const CameraMetadata& info,
+            /*out*/int32_t* outWidth, /*out*/int32_t* outHeight);
+
     // IGraphicsBufferProducer binder -> Stream ID
     KeyedVector<sp<IBinder>, int> mStreamMap;
 
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
index 2ea460f..a977494 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
@@ -50,7 +50,7 @@
     mExclusiveLock = false;
 }
 
-status_t ProCamera2Client::initialize(camera_module_t *module)
+status_t ProCamera2Client::initialize(CameraModule *module)
 {
     ATRACE_CALL();
     status_t res;
@@ -276,11 +276,12 @@
     sp<IBinder> binder;
     sp<ANativeWindow> window;
     if (bufferProducer != 0) {
-        binder = bufferProducer->asBinder();
+        binder = IInterface::asBinder(bufferProducer);
         window = new Surface(bufferProducer);
     }
 
     return mDevice->createStream(window, width, height, format,
+                                 HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0,
                                  streamId);
 }
 
@@ -334,7 +335,8 @@
     String8 result;
     result.appendFormat("ProCamera2Client[%d] (%p) PID: %d, dump:\n",
             mCameraId,
-            getRemoteCallback()->asBinder().get(),
+            (getRemoteCallback() != NULL ?
+                    IInterface::asBinder(getRemoteCallback()).get() : NULL),
             mClientPid);
     result.append("  State:\n");
     write(fd, result.string(), result.size());
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.h b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
index 9d83122..7f5f6ac 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.h
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
@@ -85,7 +85,7 @@
             int servicePid);
     virtual ~ProCamera2Client();
 
-    virtual status_t      initialize(camera_module_t *module);
+    virtual status_t      initialize(CameraModule *module);
 
     virtual status_t      dump(int fd, const Vector<String16>& args);
 
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index d6db151..0415d67 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -78,7 +78,7 @@
 }
 
 template <typename TClientBase>
-status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) {
+status_t Camera2ClientBase<TClientBase>::initialize(CameraModule *module) {
     ATRACE_CALL();
     ALOGV("%s: Initializing client for camera %d", __FUNCTION__,
           TClientBase::mCameraId);
@@ -128,7 +128,8 @@
     String8 result;
     result.appendFormat("Camera2ClientBase[%d] (%p) PID: %d, dump:\n",
             TClientBase::mCameraId,
-            TClientBase::getRemoteCallback()->asBinder().get(),
+            (TClientBase::getRemoteCallback() != NULL ?
+                    IInterface::asBinder(TClientBase::getRemoteCallback()).get() : NULL),
             TClientBase::mClientPid);
     result.append("  State: ");
 
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index d198e4e..eb21d55 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -18,6 +18,7 @@
 #define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H
 
 #include "common/CameraDeviceBase.h"
+#include "common/CameraModule.h"
 #include "camera/CaptureResult.h"
 
 namespace android {
@@ -55,7 +56,7 @@
                       int servicePid);
     virtual ~Camera2ClientBase();
 
-    virtual status_t      initialize(camera_module_t *module);
+    virtual status_t      initialize(CameraModule *module);
     virtual status_t      dump(int fd, const Vector<String16>& args);
 
     /**
@@ -111,7 +112,7 @@
     pid_t mInitialClientPid;
 
     virtual sp<IBinder> asBinderWrapper() {
-        return IInterface::asBinder();
+        return IInterface::asBinder(this);
     }
 
     virtual status_t      dumpDevice(int fd, const Vector<String16>& args);
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index d26e20c..fe55b9e 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -29,6 +29,7 @@
 #include "hardware/camera3.h"
 #include "camera/CameraMetadata.h"
 #include "camera/CaptureResult.h"
+#include "common/CameraModule.h"
 
 namespace android {
 
@@ -45,7 +46,7 @@
      */
     virtual int      getId() const = 0;
 
-    virtual status_t initialize(camera_module_t *module) = 0;
+    virtual status_t initialize(CameraModule *module) = 0;
     virtual status_t disconnect() = 0;
 
     virtual status_t dump(int fd, const Vector<String16> &args) = 0;
@@ -99,17 +100,14 @@
             nsecs_t timeout) = 0;
 
     /**
-     * Create an output stream of the requested size and format.
+     * Create an output stream of the requested size, format, rotation and dataspace
      *
-     * If format is CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, then the HAL device selects
-     * an appropriate format; it can be queried with getStreamInfo.
-     *
-     * If format is HAL_PIXEL_FORMAT_COMPRESSED, the size parameter must be
-     * equal to the size in bytes of the buffers to allocate for the stream. For
-     * other formats, the size parameter is ignored.
+     * For HAL_PIXEL_FORMAT_BLOB formats, the width and height should be the
+     * logical dimensions of the buffer, not the number of bytes.
      */
     virtual status_t createStream(sp<ANativeWindow> consumer,
-            uint32_t width, uint32_t height, int format, int *id) = 0;
+            uint32_t width, uint32_t height, int format,
+            android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id) = 0;
 
     /**
      * Create an input reprocess stream that uses buffers from an existing
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
new file mode 100644
index 0000000..5f767ad
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraModule.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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 "CameraModule"
+//#define LOG_NDEBUG 0
+
+#include "CameraModule.h"
+
+namespace android {
+
+void CameraModule::deriveCameraCharacteristicsKeys(
+        uint32_t deviceVersion, CameraMetadata &chars) {
+    // HAL1 devices should not reach here
+    if (deviceVersion < CAMERA_DEVICE_API_VERSION_2_0) {
+        ALOGV("%s: Cannot derive keys for HAL version < 2.0");
+        return;
+    }
+
+    // Keys added in HAL3.3
+    if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_3) {
+        Vector<uint8_t> controlModes;
+        uint8_t data = ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE;
+        chars.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &data, /*count*/1);
+        data = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE;
+        chars.update(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &data, /*count*/1);
+        controlModes.push(ANDROID_CONTROL_MODE_OFF);
+        controlModes.push(ANDROID_CONTROL_MODE_AUTO);
+        camera_metadata_entry entry = chars.find(ANDROID_CONTROL_AVAILABLE_SCENE_MODES);
+        if (entry.count > 1 || entry.data.u8[0] != ANDROID_CONTROL_SCENE_MODE_DISABLED) {
+            controlModes.push(ANDROID_CONTROL_MODE_USE_SCENE_MODE);
+        }
+        chars.update(ANDROID_CONTROL_AVAILABLE_MODES, controlModes);
+    }
+    return;
+}
+
+CameraModule::CameraModule(camera_module_t *module) {
+    if (module == NULL) {
+        ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
+        assert(0);
+    }
+
+    mModule = module;
+    for (int i = 0; i < MAX_CAMERAS_PER_MODULE; i++) {
+        mCameraInfoCached[i] = false;
+    }
+}
+
+int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
+    Mutex::Autolock lock(mCameraInfoLock);
+    if (cameraId < 0 || cameraId >= MAX_CAMERAS_PER_MODULE) {
+        ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
+        return -EINVAL;
+    }
+
+    // Only override static_camera_characteristics for API2 devices
+    int apiVersion = mModule->common.module_api_version;
+    if (apiVersion < CAMERA_MODULE_API_VERSION_2_0) {
+        return mModule->get_camera_info(cameraId, info);
+    }
+
+    camera_info &wrappedInfo = mCameraInfo[cameraId];
+    if (!mCameraInfoCached[cameraId]) {
+        camera_info rawInfo;
+        int ret = mModule->get_camera_info(cameraId, &rawInfo);
+        if (ret != 0) {
+            return ret;
+        }
+        CameraMetadata &m = mCameraCharacteristics[cameraId];
+        m = rawInfo.static_camera_characteristics;
+        deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
+        wrappedInfo = rawInfo;
+        wrappedInfo.static_camera_characteristics = m.getAndLock();
+        mCameraInfoCached[cameraId] = true;
+    }
+    *info = wrappedInfo;
+    return 0;
+}
+
+int CameraModule::open(const char* id, struct hw_device_t** device) {
+    return filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
+}
+
+int CameraModule::openLegacy(
+        const char* id, uint32_t halVersion, struct hw_device_t** device) {
+    return mModule->open_legacy(&mModule->common, id, halVersion, device);
+}
+
+const hw_module_t* CameraModule::getRawModule() {
+    return &mModule->common;
+}
+
+int CameraModule::getNumberOfCameras() {
+    return mModule->get_number_of_cameras();
+}
+
+int CameraModule::setCallbacks(const camera_module_callbacks_t *callbacks) {
+    return mModule->set_callbacks(callbacks);
+}
+
+bool CameraModule::isVendorTagDefined() {
+    return mModule->get_vendor_tag_ops != NULL;
+}
+
+void CameraModule::getVendorTagOps(vendor_tag_ops_t* ops) {
+    if (mModule->get_vendor_tag_ops) {
+        mModule->get_vendor_tag_ops(ops);
+    }
+}
+
+int CameraModule::setTorchMode(const char* camera_id, bool enable) {
+    return mModule->set_torch_mode(camera_id, enable);
+}
+
+
+status_t CameraModule::filterOpenErrorCode(status_t err) {
+    switch(err) {
+        case NO_ERROR:
+        case -EBUSY:
+        case -EINVAL:
+        case -EUSERS:
+            return err;
+        default:
+            break;
+    }
+    return -ENODEV;
+}
+
+
+}; // namespace android
+
diff --git a/services/camera/libcameraservice/common/CameraModule.h b/services/camera/libcameraservice/common/CameraModule.h
new file mode 100644
index 0000000..16207aa
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraModule.h
@@ -0,0 +1,65 @@
+/*
+ * 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_SERVERS_CAMERA_CAMERAMODULE_H
+#define ANDROID_SERVERS_CAMERA_CAMERAMODULE_H
+
+#include <hardware/camera.h>
+#include <camera/CameraMetadata.h>
+#include <utils/Mutex.h>
+
+/* This needs to be increased if we can have more cameras */
+#define MAX_CAMERAS_PER_MODULE 2
+
+
+namespace android {
+/**
+ * A wrapper class for HAL camera module.
+ *
+ * This class wraps camera_module_t returned from HAL to provide a wrapped
+ * get_camera_info implementation which CameraService generates some
+ * camera characteristics keys defined in newer HAL version on an older HAL.
+ */
+class CameraModule {
+public:
+    CameraModule(camera_module_t *module);
+
+    const hw_module_t* getRawModule();
+    int getCameraInfo(int cameraId, struct camera_info *info);
+    int getNumberOfCameras(void);
+    int open(const char* id, struct hw_device_t** device);
+    int openLegacy(const char* id, uint32_t halVersion, struct hw_device_t** device);
+    int setCallbacks(const camera_module_callbacks_t *callbacks);
+    bool isVendorTagDefined();
+    void getVendorTagOps(vendor_tag_ops_t* ops);
+    int setTorchMode(const char* camera_id, bool enable);
+
+private:
+    // Derive camera characteristics keys defined after HAL device version
+    static void deriveCameraCharacteristicsKeys(uint32_t deviceVersion, CameraMetadata &chars);
+    status_t filterOpenErrorCode(status_t err);
+
+    camera_module_t *mModule;
+    CameraMetadata mCameraCharacteristics[MAX_CAMERAS_PER_MODULE];
+    camera_info mCameraInfo[MAX_CAMERAS_PER_MODULE];
+    bool mCameraInfoCached[MAX_CAMERAS_PER_MODULE];
+    Mutex mCameraInfoLock;
+};
+
+} // namespace android
+
+#endif
+
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 6386838..f5ebbf8 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -89,24 +89,22 @@
         }
     }
 
-    status_t initialize(hw_module_t *module)
+    status_t initialize(CameraModule *module)
     {
         ALOGI("Opening camera %s", mName.string());
-        camera_module_t *cameraModule = reinterpret_cast<camera_module_t *>(module);
         camera_info info;
-        status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info);
+        status_t res = module->getCameraInfo(atoi(mName.string()), &info);
         if (res != OK) return res;
 
         int rc = OK;
-        if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
+        if (module->getRawModule()->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
             info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
             // Open higher version camera device as HAL1.0 device.
-            rc = cameraModule->open_legacy(module, mName.string(),
-                                               CAMERA_DEVICE_API_VERSION_1_0,
-                                               (hw_device_t **)&mDevice);
+            rc = module->openLegacy(mName.string(),
+                                     CAMERA_DEVICE_API_VERSION_1_0,
+                                     (hw_device_t **)&mDevice);
         } else {
-            rc = CameraService::filterOpenErrorCode(module->methods->open(
-                module, mName.string(), (hw_device_t **)&mDevice));
+            rc = module->open(mName.string(), (hw_device_t **)&mDevice);
         }
         if (rc != OK) {
             ALOGE("Could not open camera %s: %d", mName.string(), rc);
@@ -588,7 +586,7 @@
 
 #ifndef container_of
 #define container_of(ptr, type, member) ({                      \
-        const typeof(((type *) 0)->member) *__mptr = (ptr);     \
+        const __typeof__(((type *) 0)->member) *__mptr = (ptr);     \
         (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
 #endif
 
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index 8caadd6..878986b 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -53,7 +53,7 @@
     return mId;
 }
 
-status_t Camera2Device::initialize(camera_module_t *module)
+status_t Camera2Device::initialize(CameraModule *module)
 {
     ATRACE_CALL();
     ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
@@ -68,8 +68,7 @@
 
     camera2_device_t *device;
 
-    res = CameraService::filterOpenErrorCode(module->common.methods->open(
-        &module->common, name, reinterpret_cast<hw_device_t**>(&device)));
+    res = module->open(name, reinterpret_cast<hw_device_t**>(&device));
 
     if (res != OK) {
         ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
@@ -87,7 +86,7 @@
     }
 
     camera_info info;
-    res = module->get_camera_info(mId, &info);
+    res = module->getCameraInfo(mId, &info);
     if (res != OK ) return res;
 
     if (info.device_version != device->common.version) {
@@ -242,7 +241,8 @@
 }
 
 status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
-        uint32_t width, uint32_t height, int format, int *id) {
+        uint32_t width, uint32_t height, int format,
+        android_dataspace /*dataSpace*/, camera3_stream_rotation_t rotation, int *id) {
     ATRACE_CALL();
     status_t res;
     ALOGV("%s: E", __FUNCTION__);
@@ -793,11 +793,6 @@
         mStreamSlotCount = 0;
         return OK;
     }
-    camera_metadata_t *buf2 = clone_camera_metadata(buf);
-    if (!buf2) {
-        ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
-        return NO_MEMORY;
-    }
 
     if (mStreamSlotCount > 1) {
         List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
@@ -806,9 +801,9 @@
     }
     if (mStreamSlotCount == 1) {
         free_camera_metadata( *(mStreamSlot.begin()) );
-        *(mStreamSlot.begin()) = buf2;
+        *(mStreamSlot.begin()) = buf;
     } else {
-        mStreamSlot.push_front(buf2);
+        mStreamSlot.push_front(buf);
         mStreamSlotCount = 1;
     }
     return signalConsumerLocked();
@@ -827,12 +822,7 @@
     mStreamSlotCount = 0;
     for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
          r != bufs.end(); r++) {
-        camera_metadata_t *r2 = clone_camera_metadata(*r);
-        if (!r2) {
-            ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
-            return NO_MEMORY;
-        }
-        mStreamSlot.push_back(r2);
+        mStreamSlot.push_back(*r);
         mStreamSlotCount++;
     }
     return signalConsumerLocked();
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 2a3f1d9..9b32fa6 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -43,7 +43,7 @@
      * CameraDevice interface
      */
     virtual int      getId() const;
-    virtual status_t initialize(camera_module_t *module);
+    virtual status_t initialize(CameraModule *module);
     virtual status_t disconnect();
     virtual status_t dump(int fd, const Vector<String16>& args);
     virtual const CameraMetadata& info() const;
@@ -57,7 +57,8 @@
     virtual status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL);
     virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);
     virtual status_t createStream(sp<ANativeWindow> consumer,
-            uint32_t width, uint32_t height, int format, int *id);
+            uint32_t width, uint32_t height, int format,
+            android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id);
     virtual status_t createReprocessStreamFromStream(int outputId, int *id);
     virtual status_t getStreamInfo(int id,
             uint32_t *width, uint32_t *height, uint32_t *format);
@@ -124,8 +125,8 @@
 
         // Set repeating buffer(s); if the queue is empty on a dequeue call, the
         // queue copies the contents of the stream slot into the queue, and then
-        // dequeues the first new entry. The metadata buffers passed in are
-        // copied.
+        // dequeues the first new entry. The methods take the ownership of the
+        // metadata buffers passed in.
         status_t setStreamSlot(camera_metadata_t *buf);
         status_t setStreamSlot(const List<camera_metadata_t*> &bufs);
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 6a7f9e7..8236788 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -86,7 +86,7 @@
  * CameraDeviceBase interface
  */
 
-status_t Camera3Device::initialize(camera_module_t *module)
+status_t Camera3Device::initialize(CameraModule *module)
 {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
@@ -106,9 +106,8 @@
     camera3_device_t *device;
 
     ATRACE_BEGIN("camera3->open");
-    res = CameraService::filterOpenErrorCode(module->common.methods->open(
-        &module->common, deviceName.string(),
-        reinterpret_cast<hw_device_t**>(&device)));
+    res = module->open(deviceName.string(),
+            reinterpret_cast<hw_device_t**>(&device));
     ATRACE_END();
 
     if (res != OK) {
@@ -127,7 +126,7 @@
     }
 
     camera_info info;
-    res = CameraService::filterGetInfoErrorCode(module->get_camera_info(
+    res = CameraService::filterGetInfoErrorCode(module->getCameraInfo(
         mId, &info));
     if (res != OK) return res;
 
@@ -361,16 +360,15 @@
         return BAD_VALUE;
     }
     maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
+    assert(kMinJpegBufferSize < maxJpegBufferSize);
 
     // Calculate final jpeg buffer size for the given resolution.
     float scaleFactor = ((float) (width * height)) /
             (maxJpegResolution.width * maxJpegResolution.height);
-    ssize_t jpegBufferSize = scaleFactor * maxJpegBufferSize;
-    // Bound the buffer size to [MIN_JPEG_BUFFER_SIZE, maxJpegBufferSize].
+    ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
+            kMinJpegBufferSize;
     if (jpegBufferSize > maxJpegBufferSize) {
         jpegBufferSize = maxJpegBufferSize;
-    } else if (jpegBufferSize < kMinJpegBufferSize) {
-        jpegBufferSize = kMinJpegBufferSize;
     }
 
     return jpegBufferSize;
@@ -427,7 +425,7 @@
             InFlightRequest r = mInFlightMap.valueAt(i);
             lines.appendFormat("      Frame %d |  Timestamp: %" PRId64 ", metadata"
                     " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
-                    r.captureTimestamp, r.haveResultMetadata ? "true" : "false",
+                    r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
                     r.numBuffersLeft);
         }
     }
@@ -803,12 +801,13 @@
 }
 
 status_t Camera3Device::createStream(sp<ANativeWindow> consumer,
-        uint32_t width, uint32_t height, int format, int *id) {
+        uint32_t width, uint32_t height, int format, android_dataspace dataSpace,
+        camera3_stream_rotation_t rotation, int *id) {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
-    ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d",
-            mId, mNextStreamId, width, height, format);
+    ALOGV("Camera %d: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d",
+            mId, mNextStreamId, width, height, format, dataSpace, rotation);
 
     status_t res;
     bool wasActive = false;
@@ -848,10 +847,10 @@
         }
 
         newStream = new Camera3OutputStream(mNextStreamId, consumer,
-                width, height, jpegBufferSize, format);
+                width, height, jpegBufferSize, format, dataSpace, rotation);
     } else {
         newStream = new Camera3OutputStream(mNextStreamId, consumer,
-                width, height, format);
+                width, height, format, dataSpace, rotation);
     }
     newStream->setStatusTracker(mStatusTracker);
 
@@ -1880,6 +1879,131 @@
     return true;
 }
 
+
+void Camera3Device::returnOutputBuffers(
+        const camera3_stream_buffer_t *outputBuffers, size_t numBuffers,
+        nsecs_t timestamp) {
+    for (size_t i = 0; i < numBuffers; i++)
+    {
+        Camera3Stream *stream = Camera3Stream::cast(outputBuffers[i].stream);
+        status_t res = stream->returnBuffer(outputBuffers[i], timestamp);
+        // Note: stream may be deallocated at this point, if this buffer was
+        // the last reference to it.
+        if (res != OK) {
+            ALOGE("Can't return buffer to its stream: %s (%d)",
+                strerror(-res), res);
+        }
+    }
+}
+
+
+void Camera3Device::removeInFlightRequestIfReadyLocked(int idx) {
+
+    const InFlightRequest &request = mInFlightMap.valueAt(idx);
+    const uint32_t frameNumber = mInFlightMap.keyAt(idx);
+
+    nsecs_t sensorTimestamp = request.sensorTimestamp;
+    nsecs_t shutterTimestamp = request.shutterTimestamp;
+
+    // Check if it's okay to remove the request from InFlightMap:
+    // In the case of a successful request:
+    //      all input and output buffers, all result metadata, shutter callback
+    //      arrived.
+    // In the case of a unsuccessful request:
+    //      all input and output buffers arrived.
+    if (request.numBuffersLeft == 0 &&
+            (request.requestStatus != OK ||
+            (request.haveResultMetadata && shutterTimestamp != 0))) {
+        ATRACE_ASYNC_END("frame capture", frameNumber);
+
+        // Sanity check - if sensor timestamp matches shutter timestamp
+        if (request.requestStatus == OK &&
+                sensorTimestamp != shutterTimestamp) {
+            SET_ERR("sensor timestamp (%" PRId64
+                ") for frame %d doesn't match shutter timestamp (%" PRId64 ")",
+                sensorTimestamp, frameNumber, shutterTimestamp);
+        }
+
+        // for an unsuccessful request, it may have pending output buffers to
+        // return.
+        assert(request.requestStatus != OK ||
+               request.pendingOutputBuffers.size() == 0);
+        returnOutputBuffers(request.pendingOutputBuffers.array(),
+            request.pendingOutputBuffers.size(), 0);
+
+        mInFlightMap.removeItemsAt(idx, 1);
+
+        ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
+     }
+
+    // Sanity check - if we have too many in-flight frames, something has
+    // likely gone wrong
+    if (mInFlightMap.size() > kInFlightWarnLimit) {
+        CLOGE("In-flight list too large: %zu", mInFlightMap.size());
+    }
+}
+
+
+void Camera3Device::sendCaptureResult(CameraMetadata &pendingMetadata,
+        CaptureResultExtras &resultExtras,
+        CameraMetadata &collectedPartialResult,
+        uint32_t frameNumber) {
+    if (pendingMetadata.isEmpty())
+        return;
+
+    Mutex::Autolock l(mOutputLock);
+
+    // TODO: need to track errors for tighter bounds on expected frame number
+    if (frameNumber < mNextResultFrameNumber) {
+        SET_ERR("Out-of-order capture result metadata submitted! "
+                "(got frame number %d, expecting %d)",
+                frameNumber, mNextResultFrameNumber);
+        return;
+    }
+    mNextResultFrameNumber = frameNumber + 1;
+
+    CaptureResult captureResult;
+    captureResult.mResultExtras = resultExtras;
+    captureResult.mMetadata = pendingMetadata;
+
+    if (captureResult.mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
+            (int32_t*)&frameNumber, 1) != OK) {
+        SET_ERR("Failed to set frame# in metadata (%d)",
+                frameNumber);
+        return;
+    } else {
+        ALOGVV("%s: Camera %d: Set frame# in metadata (%d)",
+                __FUNCTION__, mId, frameNumber);
+    }
+
+    // Append any previous partials to form a complete result
+    if (mUsePartialResult && !collectedPartialResult.isEmpty()) {
+        captureResult.mMetadata.append(collectedPartialResult);
+    }
+
+    captureResult.mMetadata.sort();
+
+    // Check that there's a timestamp in the result metadata
+    camera_metadata_entry entry =
+            captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
+    if (entry.count == 0) {
+        SET_ERR("No timestamp provided by HAL for frame %d!",
+                frameNumber);
+        return;
+    }
+
+    // Valid result, insert into queue
+    List<CaptureResult>::iterator queuedResult =
+            mResultQueue.insert(mResultQueue.end(), CaptureResult(captureResult));
+    ALOGVV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
+           ", burstId = %" PRId32, __FUNCTION__,
+           queuedResult->mResultExtras.requestId,
+           queuedResult->mResultExtras.frameNumber,
+           queuedResult->mResultExtras.burstId);
+
+    mResultSignal.signal();
+}
+
 /**
  * Camera HAL device callback methods
  */
@@ -1914,11 +2038,14 @@
     CaptureResultExtras resultExtras;
     bool hasInputBufferInRequest = false;
 
-    // Get capture timestamp and resultExtras from list of in-flight requests,
-    // where it was added by the shutter notification for this frame.
-    // Then update the in-flight status and remove the in-flight entry if
-    // all result data has been received.
-    nsecs_t timestamp = 0;
+    // Get shutter timestamp and resultExtras from list of in-flight requests,
+    // where it was added by the shutter notification for this frame. If the
+    // shutter timestamp isn't received yet, append the output buffers to the
+    // in-flight request and they will be returned when the shutter timestamp
+    // arrives. Update the in-flight status and remove the in-flight entry if
+    // all result data and shutter timestamp have been received.
+    nsecs_t shutterTimestamp = 0;
+
     {
         Mutex::Autolock l(mInFlightLock);
         ssize_t idx = mInFlightMap.indexOfKey(frameNumber);
@@ -1928,13 +2055,17 @@
             return;
         }
         InFlightRequest &request = mInFlightMap.editValueAt(idx);
-        ALOGVV("%s: got InFlightRequest requestId = %" PRId32 ", frameNumber = %" PRId64
-                ", burstId = %" PRId32,
-                __FUNCTION__, request.resultExtras.requestId, request.resultExtras.frameNumber,
-                request.resultExtras.burstId);
-        // Always update the partial count to the latest one. When framework aggregates adjacent
-        // partial results into one, the latest partial count will be used.
-        request.resultExtras.partialResultCount = result->partial_result;
+        ALOGVV("%s: got InFlightRequest requestId = %" PRId32
+                ", frameNumber = %" PRId64 ", burstId = %" PRId32
+                ", partialResultCount = %d",
+                __FUNCTION__, request.resultExtras.requestId,
+                request.resultExtras.frameNumber, request.resultExtras.burstId,
+                result->partial_result);
+        // Always update the partial count to the latest one if it's not 0
+        // (buffers only). When framework aggregates adjacent partial results
+        // into one, the latest partial count will be used.
+        if (result->partial_result != 0)
+            request.resultExtras.partialResultCount = result->partial_result;
 
         // Check if this result carries only partial metadata
         if (mUsePartialResult && result->result != NULL) {
@@ -1978,22 +2109,9 @@
             }
         }
 
-        timestamp = request.captureTimestamp;
-        resultExtras = request.resultExtras;
+        shutterTimestamp = request.shutterTimestamp;
         hasInputBufferInRequest = request.hasInputBuffer;
 
-        /**
-         * One of the following must happen before it's legal to call process_capture_result,
-         * unless partial metadata is being provided:
-         * - CAMERA3_MSG_SHUTTER (expected during normal operation)
-         * - CAMERA3_MSG_ERROR (expected during flush)
-         */
-        if (request.requestStatus == OK && timestamp == 0 && !isPartialResult) {
-            SET_ERR("Called before shutter notify for frame %d",
-                    frameNumber);
-            return;
-        }
-
         // Did we get the (final) result metadata for this capture?
         if (result->result != NULL && !isPartialResult) {
             if (request.haveResultMetadata) {
@@ -2026,99 +2144,38 @@
             return;
         }
 
-        // Check if everything has arrived for this result (buffers and metadata), remove it from
-        // InFlightMap if both arrived or HAL reports error for this request (i.e. during flush).
-        if ((request.requestStatus != OK) ||
-                (request.haveResultMetadata && request.numBuffersLeft == 0)) {
-            ATRACE_ASYNC_END("frame capture", frameNumber);
-            mInFlightMap.removeItemsAt(idx, 1);
+        camera_metadata_ro_entry_t entry;
+        res = find_camera_metadata_ro_entry(result->result,
+                ANDROID_SENSOR_TIMESTAMP, &entry);
+        if (res == OK && entry.count == 1) {
+            request.sensorTimestamp = entry.data.i64[0];
         }
 
-        // Sanity check - if we have too many in-flight frames, something has
-        // likely gone wrong
-        if (mInFlightMap.size() > kInFlightWarnLimit) {
-            CLOGE("In-flight list too large: %zu", mInFlightMap.size());
-        }
-
-    }
-
-    // Process the result metadata, if provided
-    bool gotResult = false;
-    if (result->result != NULL && !isPartialResult) {
-        Mutex::Autolock l(mOutputLock);
-
-        gotResult = true;
-
-        // TODO: need to track errors for tighter bounds on expected frame number
-        if (frameNumber < mNextResultFrameNumber) {
-            SET_ERR("Out-of-order capture result metadata submitted! "
-                    "(got frame number %d, expecting %d)",
-                    frameNumber, mNextResultFrameNumber);
-            return;
-        }
-        mNextResultFrameNumber = frameNumber + 1;
-
-        CaptureResult captureResult;
-        captureResult.mResultExtras = resultExtras;
-        captureResult.mMetadata = result->result;
-
-        if (captureResult.mMetadata.update(ANDROID_REQUEST_FRAME_COUNT,
-                (int32_t*)&frameNumber, 1) != OK) {
-            SET_ERR("Failed to set frame# in metadata (%d)",
-                    frameNumber);
-            gotResult = false;
+        // If shutter event isn't received yet, append the output buffers to
+        // the in-flight request. Otherwise, return the output buffers to
+        // streams.
+        if (shutterTimestamp == 0) {
+            request.pendingOutputBuffers.appendArray(result->output_buffers,
+                result->num_output_buffers);
         } else {
-            ALOGVV("%s: Camera %d: Set frame# in metadata (%d)",
-                    __FUNCTION__, mId, frameNumber);
+            returnOutputBuffers(result->output_buffers,
+                result->num_output_buffers, shutterTimestamp);
         }
 
-        // Append any previous partials to form a complete result
-        if (mUsePartialResult && !collectedPartialResult.isEmpty()) {
-            captureResult.mMetadata.append(collectedPartialResult);
+        if (result->result != NULL && !isPartialResult) {
+            if (shutterTimestamp == 0) {
+                request.pendingMetadata = result->result;
+                request.partialResult.collectedResult = collectedPartialResult;
+            } else {
+                CameraMetadata metadata;
+                metadata = result->result;
+                sendCaptureResult(metadata, request.resultExtras,
+                    collectedPartialResult, frameNumber);
+            }
         }
 
-        captureResult.mMetadata.sort();
-
-        // Check that there's a timestamp in the result metadata
-
-        camera_metadata_entry entry =
-                captureResult.mMetadata.find(ANDROID_SENSOR_TIMESTAMP);
-        if (entry.count == 0) {
-            SET_ERR("No timestamp provided by HAL for frame %d!",
-                    frameNumber);
-            gotResult = false;
-        } else if (timestamp != entry.data.i64[0]) {
-            SET_ERR("Timestamp mismatch between shutter notify and result"
-                    " metadata for frame %d (%" PRId64 " vs %" PRId64 " respectively)",
-                    frameNumber, timestamp, entry.data.i64[0]);
-            gotResult = false;
-        }
-
-        if (gotResult) {
-            // Valid result, insert into queue
-            List<CaptureResult>::iterator queuedResult =
-                    mResultQueue.insert(mResultQueue.end(), CaptureResult(captureResult));
-            ALOGVV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
-                   ", burstId = %" PRId32, __FUNCTION__,
-                   queuedResult->mResultExtras.requestId,
-                   queuedResult->mResultExtras.frameNumber,
-                   queuedResult->mResultExtras.burstId);
-        }
-    } // scope for mOutputLock
-
-    // Return completed buffers to their streams with the timestamp
-
-    for (size_t i = 0; i < result->num_output_buffers; i++) {
-        Camera3Stream *stream =
-                Camera3Stream::cast(result->output_buffers[i].stream);
-        res = stream->returnBuffer(result->output_buffers[i], timestamp);
-        // Note: stream may be deallocated at this point, if this buffer was the
-        // last reference to it.
-        if (res != OK) {
-            ALOGE("Can't return buffer %zu for frame %d to its stream: "
-                    " %s (%d)", i, frameNumber, strerror(-res), res);
-        }
-    }
+        removeInFlightRequestIfReadyLocked(idx);
+    } // scope for mInFlightLock
 
     if (result->input_buffer != NULL) {
         if (hasInputBufferInRequest) {
@@ -2138,13 +2195,6 @@
                     __FUNCTION__);
         }
     }
-
-    // Finally, signal any waiters for new frames
-
-    if (gotResult) {
-        mResultSignal.signal();
-    }
-
 }
 
 void Camera3Device::notify(const camera3_notify_msg *msg) {
@@ -2262,8 +2312,6 @@
         mNextShutterFrameNumber = msg.frame_number + 1;
     }
 
-    CaptureResultExtras resultExtras;
-
     // Set timestamp for the request in the in-flight tracking
     // and get the request ID to send upstream
     {
@@ -2271,21 +2319,30 @@
         idx = mInFlightMap.indexOfKey(msg.frame_number);
         if (idx >= 0) {
             InFlightRequest &r = mInFlightMap.editValueAt(idx);
-            r.captureTimestamp = msg.timestamp;
-            resultExtras = r.resultExtras;
+
+            ALOGVV("Camera %d: %s: Shutter fired for frame %d (id %d) at %" PRId64,
+                    mId, __FUNCTION__,
+                    msg.frame_number, r.resultExtras.requestId, msg.timestamp);
+            // Call listener, if any
+            if (listener != NULL) {
+                listener->notifyShutter(r.resultExtras, msg.timestamp);
+            }
+
+            r.shutterTimestamp = msg.timestamp;
+
+            // send pending result and buffers
+            sendCaptureResult(r.pendingMetadata, r.resultExtras,
+                r.partialResult.collectedResult, msg.frame_number);
+            returnOutputBuffers(r.pendingOutputBuffers.array(),
+                r.pendingOutputBuffers.size(), r.shutterTimestamp);
+            r.pendingOutputBuffers.clear();
+
+            removeInFlightRequestIfReadyLocked(idx);
         }
     }
     if (idx < 0) {
         SET_ERR("Shutter notification for non-existent frame number %d",
                 msg.frame_number);
-        return;
-    }
-    ALOGVV("Camera %d: %s: Shutter fired for frame %d (id %d) at %" PRId64,
-            mId, __FUNCTION__,
-            msg.frame_number, resultExtras.requestId, msg.timestamp);
-    // Call listener, if any
-    if (listener != NULL) {
-        listener->notifyShutter(resultExtras, msg.timestamp);
     }
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index ec6bba1..a77548d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -73,7 +73,7 @@
     virtual int      getId() const;
 
     // Transitions to idle state on success.
-    virtual status_t initialize(camera_module_t *module);
+    virtual status_t initialize(CameraModule *module);
     virtual status_t disconnect();
     virtual status_t dump(int fd, const Vector<String16> &args);
     virtual const CameraMetadata& info() const;
@@ -95,7 +95,8 @@
     // If adding streams while actively capturing, will pause device before adding
     // stream, reconfiguring device, and unpausing.
     virtual status_t createStream(sp<ANativeWindow> consumer,
-            uint32_t width, uint32_t height, int format, int *id);
+            uint32_t width, uint32_t height, int format,
+            android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id);
     virtual status_t createInputStream(
             uint32_t width, uint32_t height, int format,
             int *id);
@@ -521,7 +522,9 @@
 
     struct InFlightRequest {
         // Set by notify() SHUTTER call.
-        nsecs_t captureTimestamp;
+        nsecs_t shutterTimestamp;
+        // Set by process_capture_result().
+        nsecs_t sensorTimestamp;
         int     requestStatus;
         // Set by process_capture_result call with valid metadata
         bool    haveResultMetadata;
@@ -532,6 +535,21 @@
         // If this request has any input buffer
         bool hasInputBuffer;
 
+
+        // The last metadata that framework receives from HAL and
+        // not yet send out because the shutter event hasn't arrived.
+        // It's added by process_capture_result and sent when framework
+        // receives the shutter event.
+        CameraMetadata pendingMetadata;
+
+        // Buffers are added by process_capture_result when output buffers
+        // return from HAL but framework has not yet received the shutter
+        // event. They will be returned to the streams when framework receives
+        // the shutter event.
+        Vector<camera3_stream_buffer_t> pendingOutputBuffers;
+
+
+
         // Fields used by the partial result only
         struct PartialResultInFlight {
             // Set by process_capture_result once 3A has been sent to clients
@@ -546,7 +564,8 @@
 
         // Default constructor needed by KeyedVector
         InFlightRequest() :
-                captureTimestamp(0),
+                shutterTimestamp(0),
+                sensorTimestamp(0),
                 requestStatus(OK),
                 haveResultMetadata(false),
                 numBuffersLeft(0),
@@ -554,7 +573,8 @@
         }
 
         InFlightRequest(int numBuffers) :
-                captureTimestamp(0),
+                shutterTimestamp(0),
+                sensorTimestamp(0),
                 requestStatus(OK),
                 haveResultMetadata(false),
                 numBuffersLeft(numBuffers),
@@ -562,7 +582,8 @@
         }
 
         InFlightRequest(int numBuffers, CaptureResultExtras extras) :
-                captureTimestamp(0),
+                shutterTimestamp(0),
+                sensorTimestamp(0),
                 requestStatus(OK),
                 haveResultMetadata(false),
                 numBuffersLeft(numBuffers),
@@ -571,7 +592,8 @@
         }
 
         InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput) :
-                captureTimestamp(0),
+                shutterTimestamp(0),
+                sensorTimestamp(0),
                 requestStatus(OK),
                 haveResultMetadata(false),
                 numBuffersLeft(numBuffers),
@@ -639,6 +661,24 @@
     void notifyShutter(const camera3_shutter_msg_t &msg,
             NotificationListener *listener);
 
+    // helper function to return the output buffers to the streams.
+    void returnOutputBuffers(const camera3_stream_buffer_t *outputBuffers,
+            size_t numBuffers, nsecs_t timestamp);
+
+    // Insert the capture result given the pending metadata, result extras,
+    // partial results, and the frame number to the result queue.
+    void sendCaptureResult(CameraMetadata &pendingMetadata,
+            CaptureResultExtras &resultExtras,
+            CameraMetadata &collectedPartialResult, uint32_t frameNumber);
+
+    /**** Scope for mInFlightLock ****/
+
+    // Remove the in-flight request of the given index from mInFlightMap
+    // if it's no longer needed. It must only be called with mInFlightLock held.
+    void removeInFlightRequestIfReadyLocked(int idx);
+
+    /**** End scope for mInFlightLock ****/
+
     /**
      * Static callback forwarding methods from HAL to instance
      */
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 6656b09..01edfff 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -28,7 +28,7 @@
 
 Camera3DummyStream::Camera3DummyStream(int id) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, DUMMY_WIDTH, DUMMY_HEIGHT,
-                /*maxSize*/0, DUMMY_FORMAT) {
+                /*maxSize*/0, DUMMY_FORMAT, DUMMY_DATASPACE, DUMMY_ROTATION) {
 
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 3e42623..d023c57 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -75,6 +75,8 @@
     static const int DUMMY_WIDTH = 320;
     static const int DUMMY_HEIGHT = 240;
     static const int DUMMY_FORMAT = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+    static const android_dataspace DUMMY_DATASPACE = HAL_DATASPACE_UNKNOWN;
+    static const camera3_stream_rotation_t DUMMY_ROTATION = CAMERA3_STREAM_ROTATION_0;
     static const uint32_t DUMMY_USAGE = GRALLOC_USAGE_HW_COMPOSER;
 
     /**
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index cc66459..8696413 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -30,9 +30,10 @@
 namespace camera3 {
 
 Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type,
-        uint32_t width, uint32_t height, size_t maxSize, int format) :
+        uint32_t width, uint32_t height, size_t maxSize, int format,
+        android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
         Camera3Stream(id, type,
-                width, height, maxSize, format),
+                width, height, maxSize, format, dataSpace, rotation),
         mTotalBufferCount(0),
         mHandoutTotalBufferCount(0),
         mHandoutOutputBufferCount(0),
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index a35c290..abcf2b1 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -33,7 +33,8 @@
         public Camera3Stream {
   protected:
     Camera3IOStreamBase(int id, camera3_stream_type_t type,
-            uint32_t width, uint32_t height, size_t maxSize, int format);
+            uint32_t width, uint32_t height, size_t maxSize, int format,
+            android_dataspace dataSpace, camera3_stream_rotation_t rotation);
 
   public:
 
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 319be1d..6bf671e 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -18,6 +18,7 @@
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
+#include <gui/BufferItem.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
 #include "Camera3InputStream.h"
@@ -28,8 +29,8 @@
 
 Camera3InputStream::Camera3InputStream(int id,
         uint32_t width, uint32_t height, int format) :
-        Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height,
-                            /*maxSize*/0, format) {
+        Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0,
+                            format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0) {
 
     if (format == HAL_PIXEL_FORMAT_BLOB) {
         ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__);
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index ae49467..fd17f4f 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -48,8 +48,6 @@
 
   private:
 
-    typedef BufferItemConsumer::BufferItem BufferItem;
-
     sp<BufferItemConsumer> mConsumer;
     Vector<BufferItem> mBuffersInFlight;
 
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 77ad503..96bed0d 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -33,9 +33,10 @@
 
 Camera3OutputStream::Camera3OutputStream(int id,
         sp<ANativeWindow> consumer,
-        uint32_t width, uint32_t height, int format) :
+        uint32_t width, uint32_t height, int format,
+        android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
-                            /*maxSize*/0, format),
+                            /*maxSize*/0, format, dataSpace, rotation),
         mConsumer(consumer),
         mTransform(0),
         mTraceFirstBuffer(true) {
@@ -48,9 +49,10 @@
 
 Camera3OutputStream::Camera3OutputStream(int id,
         sp<ANativeWindow> consumer,
-        uint32_t width, uint32_t height, size_t maxSize, int format) :
+        uint32_t width, uint32_t height, size_t maxSize, int format,
+        android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
-                            format),
+                            format, dataSpace, rotation),
         mConsumer(consumer),
         mTransform(0),
         mTraceFirstBuffer(true) {
@@ -69,10 +71,12 @@
 
 Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type,
                                          uint32_t width, uint32_t height,
-                                         int format) :
+                                         int format,
+                                         android_dataspace dataSpace,
+                                         camera3_stream_rotation_t rotation) :
         Camera3IOStreamBase(id, type, width, height,
                             /*maxSize*/0,
-                            format),
+                            format, dataSpace, rotation),
         mTransform(0) {
 
     // Subclasses expected to initialize mConsumer themselves
@@ -323,6 +327,14 @@
         return res;
     }
 
+    res = native_window_set_buffers_data_space(mConsumer.get(),
+            camera3_stream::data_space);
+    if (res != OK) {
+        ALOGE("%s: Unable to configure stream dataspace %#x for stream %d",
+                __FUNCTION__, camera3_stream::data_space, mId);
+        return res;
+    }
+
     int maxConsumerBuffers;
     res = mConsumer->query(mConsumer.get(),
             NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index be278c5..12b2ebb 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -39,14 +39,16 @@
      * Set up a stream for formats that have 2 dimensions, such as RAW and YUV.
      */
     Camera3OutputStream(int id, sp<ANativeWindow> consumer,
-            uint32_t width, uint32_t height, int format);
+            uint32_t width, uint32_t height, int format,
+            android_dataspace dataSpace, camera3_stream_rotation_t rotation);
 
     /**
      * Set up a stream for formats that have a variable buffer size for the same
      * dimensions, such as compressed JPEG.
      */
     Camera3OutputStream(int id, sp<ANativeWindow> consumer,
-            uint32_t width, uint32_t height, size_t maxSize, int format);
+            uint32_t width, uint32_t height, size_t maxSize, int format,
+            android_dataspace dataSpace, camera3_stream_rotation_t rotation);
 
     virtual ~Camera3OutputStream();
 
@@ -64,7 +66,8 @@
 
   protected:
     Camera3OutputStream(int id, camera3_stream_type_t type,
-            uint32_t width, uint32_t height, int format);
+            uint32_t width, uint32_t height, int format,
+            android_dataspace dataSpace, camera3_stream_rotation_t rotation);
 
     /**
      * Note that we release the lock briefly in this function
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 3c0e908..4acbce3 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -46,7 +46,8 @@
 
 Camera3Stream::Camera3Stream(int id,
         camera3_stream_type type,
-        uint32_t width, uint32_t height, size_t maxSize, int format) :
+        uint32_t width, uint32_t height, size_t maxSize, int format,
+        android_dataspace dataSpace, camera3_stream_rotation_t rotation) :
     camera3_stream(),
     mId(id),
     mName(String8::format("Camera3Stream[%d]", id)),
@@ -58,6 +59,8 @@
     camera3_stream::width = width;
     camera3_stream::height = height;
     camera3_stream::format = format;
+    camera3_stream::data_space = dataSpace;
+    camera3_stream::rotation = rotation;
     camera3_stream::usage = 0;
     camera3_stream::max_buffers = 0;
     camera3_stream::priv = NULL;
@@ -84,6 +87,10 @@
     return camera3_stream::format;
 }
 
+android_dataspace Camera3Stream::getDataSpace() const {
+    return camera3_stream::data_space;
+}
+
 camera3_stream* Camera3Stream::startConfiguration() {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index d0e1337..aba27fe 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -119,9 +119,10 @@
     /**
      * Get the stream's dimensions and format
      */
-    uint32_t         getWidth() const;
-    uint32_t         getHeight() const;
-    int              getFormat() const;
+    uint32_t          getWidth() const;
+    uint32_t          getHeight() const;
+    int               getFormat() const;
+    android_dataspace getDataSpace() const;
 
     /**
      * Start the stream configuration process. Returns a handle to the stream's
@@ -264,7 +265,8 @@
     mutable Mutex mLock;
 
     Camera3Stream(int id, camera3_stream_type type,
-            uint32_t width, uint32_t height, size_t maxSize, int format);
+            uint32_t width, uint32_t height, size_t maxSize, int format,
+            android_dataspace dataSpace, camera3_stream_rotation_t rotation);
 
     /**
      * Interface to be implemented by derived classes
diff --git a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
index 81330ea..10d7f2e 100644
--- a/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3ZslStream.cpp
@@ -114,7 +114,8 @@
         int bufferCount) :
         Camera3OutputStream(id, CAMERA3_STREAM_BIDIRECTIONAL,
                             width, height,
-                            HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
+                            HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
+                            HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0),
         mDepth(bufferCount) {
 
     sp<IGraphicBufferProducer> producer;
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
index f8562ec..8cd6800 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
@@ -268,7 +268,7 @@
     return OK;
 }
 
-void RingBufferConsumer::onFrameAvailable() {
+void RingBufferConsumer::onFrameAvailable(const BufferItem& item) {
     status_t err;
 
     {
@@ -321,7 +321,7 @@
         item.mGraphicBuffer = mSlots[item.mBuf].mGraphicBuffer;
     } // end of mMutex lock
 
-    ConsumerBase::onFrameAvailable();
+    ConsumerBase::onFrameAvailable(item);
 }
 
 void RingBufferConsumer::unpinBuffer(const BufferItem& item) {
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.h b/services/camera/libcameraservice/gui/RingBufferConsumer.h
index da97a11..83e7298 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.h
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_GUI_RINGBUFFERCONSUMER_H
 #define ANDROID_GUI_RINGBUFFERCONSUMER_H
 
+#include <gui/BufferItem.h>
 #include <gui/ConsumerBase.h>
 
 #include <ui/GraphicBuffer.h>
@@ -54,8 +55,6 @@
   public:
     typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
 
-    typedef BufferQueue::BufferItem BufferItem;
-
     enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
     enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };
 
@@ -165,7 +164,7 @@
   private:
 
     // Override ConsumerBase::onFrameAvailable
-    virtual void onFrameAvailable();
+    virtual void onFrameAvailable(const BufferItem& item);
 
     void pinBufferLocked(const BufferItem& item);
     void unpinBuffer(const BufferItem& item);
diff --git a/services/camera/libcameraservice/utils/AutoConditionLock.cpp b/services/camera/libcameraservice/utils/AutoConditionLock.cpp
new file mode 100644
index 0000000..c8ee965
--- /dev/null
+++ b/services/camera/libcameraservice/utils/AutoConditionLock.cpp
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+#include "AutoConditionLock.h"
+
+namespace android {
+
+WaitableMutexWrapper::WaitableMutexWrapper(Mutex* mutex) : mMutex{mutex}, mState{false} {}
+
+WaitableMutexWrapper::~WaitableMutexWrapper() {}
+
+// Locks manager-owned mutex
+AutoConditionLock::AutoConditionLock(const std::shared_ptr<WaitableMutexWrapper>& manager) :
+        mManager{manager}, mAutoLock{manager->mMutex} {}
+
+// Unlocks manager-owned mutex
+AutoConditionLock::~AutoConditionLock() {
+    // Unset the condition and wake everyone up before releasing lock
+    mManager->mState = false;
+    mManager->mCondition.broadcast();
+}
+
+std::unique_ptr<AutoConditionLock> AutoConditionLock::waitAndAcquire(
+        const std::shared_ptr<WaitableMutexWrapper>& manager, nsecs_t waitTime) {
+
+    if (manager == nullptr || manager->mMutex == nullptr) {
+        // Bad input, return null
+        return std::unique_ptr<AutoConditionLock>{nullptr};
+    }
+
+    // Acquire scoped lock
+    std::unique_ptr<AutoConditionLock> scopedLock(new AutoConditionLock(manager));
+
+    // Figure out what time in the future we should hit the timeout
+    nsecs_t failTime = systemTime(SYSTEM_TIME_MONOTONIC) + waitTime;
+
+    // Wait until we timeout, or success
+    while(manager->mState) {
+        status_t ret = manager->mCondition.waitRelative(*(manager->mMutex), waitTime);
+        if (ret != NO_ERROR) {
+            // Timed out or whatever, return null
+            return std::unique_ptr<AutoConditionLock>{nullptr};
+        }
+        waitTime = failTime - systemTime(SYSTEM_TIME_MONOTONIC);
+    }
+
+    // Set the condition and return
+    manager->mState = true;
+    return scopedLock;
+}
+
+std::unique_ptr<AutoConditionLock> AutoConditionLock::waitAndAcquire(
+        const std::shared_ptr<WaitableMutexWrapper>& manager) {
+
+    if (manager == nullptr || manager->mMutex == nullptr) {
+        // Bad input, return null
+        return std::unique_ptr<AutoConditionLock>{nullptr};
+    }
+
+    // Acquire scoped lock
+    std::unique_ptr<AutoConditionLock> scopedLock(new AutoConditionLock(manager));
+
+    // Wait until we timeout, or success
+    while(manager->mState) {
+        status_t ret = manager->mCondition.wait(*(manager->mMutex));
+        if (ret != NO_ERROR) {
+            // Timed out or whatever, return null
+            return std::unique_ptr<AutoConditionLock>{nullptr};
+        }
+    }
+
+    // Set the condition and return
+    manager->mState = true;
+    return scopedLock;
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/utils/AutoConditionLock.h b/services/camera/libcameraservice/utils/AutoConditionLock.h
new file mode 100644
index 0000000..9a3eafc
--- /dev/null
+++ b/services/camera/libcameraservice/utils/AutoConditionLock.h
@@ -0,0 +1,99 @@
+/*
+ * 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_SERVICE_UTILS_SCOPED_CONDITION_H
+#define ANDROID_SERVICE_UTILS_SCOPED_CONDITION_H
+
+#include <utils/Timers.h>
+#include <utils/Condition.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+
+#include <memory>
+
+namespace android {
+
+/**
+ * WaitableMutexWrapper can be used with AutoConditionLock to construct scoped locks for the
+ * wrapped Mutex with timeouts for lock acquisition.
+ */
+class WaitableMutexWrapper {
+    friend class AutoConditionLock;
+public:
+    /**
+     * Construct the ConditionManger with the given Mutex.
+     */
+    WaitableMutexWrapper(Mutex* mutex);
+
+    virtual ~WaitableMutexWrapper();
+private:
+    Mutex* mMutex;
+    bool mState;
+    Condition mCondition;
+};
+
+/**
+ * AutoConditionLock is a scoped lock similar to Mutex::Autolock, but allows timeouts to be
+ * specified for lock acquisition.
+ *
+ * AutoConditionLock is used with a WaitableMutexWrapper to lock/unlock the WaitableMutexWrapper's
+ * wrapped Mutex, and wait/set/signal the WaitableMutexWrapper's wrapped condition. To use this,
+ * call AutoConditionLock::waitAndAcquire to get an instance.  This will:
+ *      - Lock the given WaitableMutexWrapper's mutex.
+ *      - Wait for the WaitableMutexWrapper's condition to become false, or timeout.
+ *      - Set the WaitableMutexWrapper's condition to true.
+ *
+ * When the AutoConditionLock goes out of scope and is destroyed, this will:
+ *      - Set the WaitableMutexWrapper's condition to false.
+ *      - Signal threads waiting on this condition to wakeup.
+ *      - Release WaitableMutexWrapper's mutex.
+ */
+class AutoConditionLock final {
+public:
+    AutoConditionLock() = delete;
+    AutoConditionLock(const AutoConditionLock& other) = delete;
+    AutoConditionLock & operator=(const AutoConditionLock&) = delete;
+
+    ~AutoConditionLock();
+
+    /**
+     * Make a new AutoConditionLock from a given WaitableMutexWrapper, waiting up to waitTime
+     * nanoseconds to acquire the WaitableMutexWrapper's wrapped lock.
+     *
+     * Return an empty unique_ptr if this fails, or a timeout occurs.
+     */
+    static std::unique_ptr<AutoConditionLock> waitAndAcquire(
+            const std::shared_ptr<WaitableMutexWrapper>& manager, nsecs_t waitTime);
+
+    /**
+     * Make a new AutoConditionLock from a given WaitableMutexWrapper, waiting indefinitely to
+     * acquire the WaitableMutexWrapper's wrapped lock.
+     *
+     * Return an empty unique_ptr if this fails.
+     */
+    static std::unique_ptr<AutoConditionLock> waitAndAcquire(
+            const std::shared_ptr<WaitableMutexWrapper>& manager);
+private:
+    AutoConditionLock(const std::shared_ptr<WaitableMutexWrapper>& manager);
+
+    std::shared_ptr<WaitableMutexWrapper> mManager;
+    Mutex::Autolock mAutoLock;
+};
+
+}; // namespace android
+
+#endif // ANDROID_SERVICE_UTILS_SCOPED_CONDITION_H
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
new file mode 100644
index 0000000..ad5486d
--- /dev/null
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -0,0 +1,539 @@
+/*
+ * 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_SERVICE_UTILS_EVICTION_POLICY_MANAGER_H
+#define ANDROID_SERVICE_UTILS_EVICTION_POLICY_MANAGER_H
+
+#include <utils/Mutex.h>
+
+#include <algorithm>
+#include <utility>
+#include <vector>
+#include <set>
+#include <map>
+#include <memory>
+
+namespace android {
+namespace resource_policy {
+
+// --------------------------------------------------------------------------------
+
+/**
+ * The ClientDescriptor class is a container for a given key/value pair identifying a shared
+ * resource, and the corresponding cost, priority, owner ID, and conflicting keys list used
+ * in determining eviction behavior.
+ *
+ * Aside from the priority, these values are immutable once the ClientDescriptor has been
+ * constructed.
+ */
+template<class KEY, class VALUE>
+class ClientDescriptor final {
+public:
+    ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
+            const std::set<KEY>& conflictingKeys, int32_t priority, int32_t ownerId);
+    ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost, std::set<KEY>&& conflictingKeys,
+            int32_t priority, int32_t ownerId);
+
+    ~ClientDescriptor();
+
+    /**
+     * Return the key for this descriptor.
+     */
+    const KEY& getKey() const;
+
+    /**
+     * Return the value for this descriptor.
+     */
+    const VALUE& getValue() const;
+
+    /**
+     * Return the cost for this descriptor.
+     */
+    int32_t getCost() const;
+
+    /**
+     * Return the priority for this descriptor.
+     */
+    int32_t getPriority() const;
+
+    /**
+     * Return the owner ID for this descriptor.
+     */
+    int32_t getOwnerId() const;
+
+    /**
+     * Return true if the given key is in this descriptor's conflicting keys list.
+     */
+    bool isConflicting(const KEY& key) const;
+
+    /**
+     * Return the set of all conflicting keys for this descriptor.
+     */
+    std::set<KEY> getConflicting() const;
+
+    /**
+     * Set the proirity for this descriptor.
+     */
+    void setPriority(int32_t priority);
+
+    // This class is ordered by key
+    template<class K, class V>
+    friend bool operator < (const ClientDescriptor<K, V>& a, const ClientDescriptor<K, V>& b);
+
+private:
+    KEY mKey;
+    VALUE mValue;
+    int32_t mCost;
+    std::set<KEY> mConflicting;
+    int32_t mPriority;
+    int32_t mOwnerId;
+}; // class ClientDescriptor
+
+template<class K, class V>
+bool operator < (const ClientDescriptor<K, V>& a, const ClientDescriptor<K, V>& b) {
+    return a.mKey < b.mKey;
+}
+
+template<class KEY, class VALUE>
+ClientDescriptor<KEY, VALUE>::ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
+        const std::set<KEY>& conflictingKeys, int32_t priority, int32_t ownerId) : mKey{key},
+        mValue{value}, mCost{cost}, mConflicting{conflictingKeys}, mPriority{priority},
+        mOwnerId{ownerId} {}
+
+template<class KEY, class VALUE>
+ClientDescriptor<KEY, VALUE>::ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost,
+        std::set<KEY>&& conflictingKeys, int32_t priority, int32_t ownerId) :
+        mKey{std::forward<KEY>(key)}, mValue{std::forward<VALUE>(value)}, mCost{cost},
+        mConflicting{std::forward<std::set<KEY>>(conflictingKeys)}, mPriority{priority},
+        mOwnerId{ownerId} {}
+
+template<class KEY, class VALUE>
+ClientDescriptor<KEY, VALUE>::~ClientDescriptor() {}
+
+template<class KEY, class VALUE>
+const KEY& ClientDescriptor<KEY, VALUE>::getKey() const {
+    return mKey;
+}
+
+template<class KEY, class VALUE>
+const VALUE& ClientDescriptor<KEY, VALUE>::getValue() const {
+    return mValue;
+}
+
+template<class KEY, class VALUE>
+int32_t ClientDescriptor<KEY, VALUE>::getCost() const {
+    return mCost;
+}
+
+template<class KEY, class VALUE>
+int32_t ClientDescriptor<KEY, VALUE>::getPriority() const {
+    return mPriority;
+}
+
+template<class KEY, class VALUE>
+int32_t ClientDescriptor<KEY, VALUE>::getOwnerId() const {
+    return mOwnerId;
+}
+
+template<class KEY, class VALUE>
+bool ClientDescriptor<KEY, VALUE>::isConflicting(const KEY& key) const {
+    if (key == mKey) return true;
+    for (const auto& x : mConflicting) {
+        if (key == x) return true;
+    }
+    return false;
+}
+
+template<class KEY, class VALUE>
+std::set<KEY> ClientDescriptor<KEY, VALUE>::getConflicting() const {
+    return mConflicting;
+}
+
+template<class KEY, class VALUE>
+void ClientDescriptor<KEY, VALUE>::setPriority(int32_t priority) {
+    mPriority = priority;
+}
+
+// --------------------------------------------------------------------------------
+
+/**
+ * The ClientManager class wraps an LRU-ordered list of active clients and implements eviction
+ * behavior for handling shared resource access.
+ *
+ * When adding a new descriptor, eviction behavior is as follows:
+ *   - Keys are unique, adding a descriptor with the same key as an existing descriptor will
+ *     result in the lower-priority of the two being removed.  Priority ties result in the
+ *     LRU descriptor being evicted (this means the incoming descriptor be added in this case).
+ *   - Any descriptors with keys that are in the incoming descriptor's 'conflicting keys' list
+ *     will be removed if they have an equal or lower priority than the incoming descriptor;
+ *     if any have a higher priority, the incoming descriptor is removed instead.
+ *   - If the sum of all descriptors' costs, including the incoming descriptor's, is more than
+ *     the max cost allowed for this ClientManager, descriptors with non-zero cost, equal or lower
+ *     priority, and a different owner will be evicted in LRU order until either the cost is less
+ *     than the max cost, or all descriptors meeting this criteria have been evicted and the
+ *     incoming descriptor has the highest priority.  Otherwise, the incoming descriptor is
+ *     removed instead.
+ */
+template<class KEY, class VALUE>
+class ClientManager {
+public:
+    // The default maximum "cost" allowed before evicting
+    static constexpr int32_t DEFAULT_MAX_COST = 100;
+
+    ClientManager();
+    ClientManager(int32_t totalCost);
+
+    /**
+     * Add a given ClientDescriptor to the managed list.  ClientDescriptors for clients that
+     * are evicted by this action are returned in a vector.
+     *
+     * This may return the ClientDescriptor passed in if it would be evicted.
+     */
+    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> addAndEvict(
+            const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client);
+
+    /**
+     * Given a map containing owner (pid) -> priority mappings, update the priority of each
+     * ClientDescriptor with an owner in this mapping.
+     */
+    void updatePriorities(const std::map<int32_t,int32_t>& ownerPriorityList);
+
+    /**
+     * Remove all ClientDescriptors.
+     */
+    void removeAll();
+
+    /**
+     * Remove and return the ClientDescriptor with a given key.
+     */
+    std::shared_ptr<ClientDescriptor<KEY, VALUE>> remove(const KEY& key);
+
+    /**
+     * Remove the given ClientDescriptor.
+     */
+    void remove(const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value);
+
+    /**
+     * Return a vector of the ClientDescriptors that would be evicted by adding the given
+     * ClientDescriptor.
+     *
+     * This may return the ClientDescriptor passed in if it would be evicted.
+     */
+    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> wouldEvict(
+            const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const;
+
+    /**
+     * Return a vector of active ClientDescriptors that prevent this client from being added.
+     */
+    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> getIncompatibleClients(
+            const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const;
+
+    /**
+     * Return a vector containing all currently active ClientDescriptors.
+     */
+    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> getAll() const;
+
+    /**
+     * Return a vector containing all keys of currently active ClientDescriptors.
+     */
+    std::vector<KEY> getAllKeys() const;
+
+    /**
+     * Return a vector of the owner tags of all currently active ClientDescriptors (duplicates
+     * will be removed).
+     */
+    std::vector<int32_t> getAllOwners() const;
+
+    /**
+     * Return the ClientDescriptor corresponding to the given key, or an empty shared pointer
+     * if none exists.
+     */
+    std::shared_ptr<ClientDescriptor<KEY, VALUE>> get(const KEY& key) const;
+
+protected:
+    ~ClientManager();
+
+private:
+
+    /**
+     * Return a vector of the ClientDescriptors that would be evicted by adding the given
+     * ClientDescriptor.  If returnIncompatibleClients is set to true, instead, return the
+     * vector of ClientDescriptors that are higher priority than the incoming client and
+     * either conflict with this client, or contribute to the resource cost if that would
+     * prevent the incoming client from being added.
+     *
+     * This may return the ClientDescriptor passed in.
+     */
+    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> wouldEvictLocked(
+            const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
+            bool returnIncompatibleClients = false) const;
+
+    int64_t getCurrentCostLocked() const;
+
+    mutable Mutex mLock;
+    int32_t mMaxCost;
+    // LRU ordered, most recent at end
+    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> mClients;
+}; // class ClientManager
+
+template<class KEY, class VALUE>
+ClientManager<KEY, VALUE>::ClientManager() :
+        ClientManager(DEFAULT_MAX_COST) {}
+
+template<class KEY, class VALUE>
+ClientManager<KEY, VALUE>::ClientManager(int32_t totalCost) : mMaxCost(totalCost) {}
+
+template<class KEY, class VALUE>
+ClientManager<KEY, VALUE>::~ClientManager() {}
+
+template<class KEY, class VALUE>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> ClientManager<KEY, VALUE>::wouldEvict(
+        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const {
+    Mutex::Autolock lock(mLock);
+    return wouldEvictLocked(client);
+}
+
+template<class KEY, class VALUE>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
+ClientManager<KEY, VALUE>::getIncompatibleClients(
+        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const {
+    Mutex::Autolock lock(mLock);
+    return wouldEvictLocked(client, /*returnIncompatibleClients*/true);
+}
+
+template<class KEY, class VALUE>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
+ClientManager<KEY, VALUE>::wouldEvictLocked(
+        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
+        bool returnIncompatibleClients) const {
+
+    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> evictList;
+
+    // Disallow null clients, return input
+    if (client == nullptr) {
+        evictList.push_back(client);
+        return evictList;
+    }
+
+    const KEY& key = client->getKey();
+    int32_t cost = client->getCost();
+    int32_t priority = client->getPriority();
+    int32_t owner = client->getOwnerId();
+
+    int64_t totalCost = getCurrentCostLocked() + cost;
+
+    // Determine the MRU of the owners tied for having the highest priority
+    int32_t highestPriorityOwner = owner;
+    int32_t highestPriority = priority;
+    for (const auto& i : mClients) {
+        int32_t curPriority = i->getPriority();
+        if (curPriority >= highestPriority) {
+            highestPriority = curPriority;
+            highestPriorityOwner = i->getOwnerId();
+        }
+    }
+
+    if (highestPriority == priority) {
+        // Switch back owner if the incoming client has the highest priority, as it is MRU
+        highestPriorityOwner = owner;
+    }
+
+    // Build eviction list of clients to remove
+    for (const auto& i : mClients) {
+        const KEY& curKey = i->getKey();
+        int32_t curCost = i->getCost();
+        int32_t curPriority = i->getPriority();
+        int32_t curOwner = i->getOwnerId();
+
+        bool conflicting = (curKey == key || i->isConflicting(key) ||
+                client->isConflicting(curKey));
+
+        if (!returnIncompatibleClients) {
+            // Find evicted clients
+
+            if (conflicting && curPriority > priority) {
+                // Pre-existing conflicting client with higher priority exists
+                evictList.clear();
+                evictList.push_back(client);
+                return evictList;
+            } else if (conflicting || ((totalCost > mMaxCost && curCost > 0) &&
+                    (curPriority <= priority) &&
+                    !(highestPriorityOwner == owner && owner == curOwner))) {
+                // Add a pre-existing client to the eviction list if:
+                // - We are adding a client with higher priority that conflicts with this one.
+                // - The total cost including the incoming client's is more than the allowable
+                //   maximum, and the client has a non-zero cost, lower priority, and a different
+                //   owner than the incoming client when the incoming client has the
+                //   highest priority.
+                evictList.push_back(i);
+                totalCost -= curCost;
+            }
+        } else {
+            // Find clients preventing the incoming client from being added
+
+            if (curPriority > priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
+                // Pre-existing conflicting client with higher priority exists
+                evictList.push_back(i);
+            }
+        }
+    }
+
+    // Immediately return the incompatible clients if we are calculating these instead
+    if (returnIncompatibleClients) {
+        return evictList;
+    }
+
+    // If the total cost is too high, return the input unless the input has the highest priority
+    if (totalCost > mMaxCost && highestPriorityOwner != owner) {
+        evictList.clear();
+        evictList.push_back(client);
+        return evictList;
+    }
+
+    return evictList;
+
+}
+
+template<class KEY, class VALUE>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> ClientManager<KEY, VALUE>::addAndEvict(
+        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) {
+    Mutex::Autolock lock(mLock);
+    auto evicted = wouldEvictLocked(client);
+    auto it = evicted.begin();
+    if (it != evicted.end() && *it == client) {
+        return evicted;
+    }
+
+    auto iter = evicted.cbegin();
+
+    // Remove evicted clients from list
+    mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
+        [&iter] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
+            if (curClientPtr->getKey() == (*iter)->getKey()) {
+                iter++;
+                return true;
+            }
+            return false;
+        }), mClients.end());
+
+    mClients.push_back(client);
+
+    return evicted;
+}
+
+template<class KEY, class VALUE>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
+ClientManager<KEY, VALUE>::getAll() const {
+    Mutex::Autolock lock(mLock);
+    return mClients;
+}
+
+template<class KEY, class VALUE>
+std::vector<KEY> ClientManager<KEY, VALUE>::getAllKeys() const {
+    Mutex::Autolock lock(mLock);
+    std::vector<KEY> keys(mClients.size());
+    for (const auto& i : mClients) {
+        keys.push_back(i->getKey());
+    }
+    return keys;
+}
+
+template<class KEY, class VALUE>
+std::vector<int32_t> ClientManager<KEY, VALUE>::getAllOwners() const {
+    Mutex::Autolock lock(mLock);
+    std::set<int32_t> owners;
+    for (const auto& i : mClients) {
+        owners.emplace(i->getOwnerId());
+    }
+    return std::vector<int32_t>(owners.begin(), owners.end());
+}
+
+template<class KEY, class VALUE>
+void ClientManager<KEY, VALUE>::updatePriorities(
+        const std::map<int32_t,int32_t>& ownerPriorityList) {
+    Mutex::Autolock lock(mLock);
+    for (auto& i : mClients) {
+        auto j = ownerPriorityList.find(i->getOwnerId());
+        if (j != ownerPriorityList.end()) {
+            i->setPriority(j->second);
+        }
+    }
+}
+
+template<class KEY, class VALUE>
+std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE>::get(
+        const KEY& key) const {
+    Mutex::Autolock lock(mLock);
+    for (const auto& i : mClients) {
+        if (i->getKey() == key) return i;
+    }
+    return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
+}
+
+template<class KEY, class VALUE>
+void ClientManager<KEY, VALUE>::removeAll() {
+    Mutex::Autolock lock(mLock);
+    mClients.clear();
+}
+
+template<class KEY, class VALUE>
+std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE>::remove(const KEY& key) {
+    Mutex::Autolock lock(mLock);
+
+    std::shared_ptr<ClientDescriptor<KEY, VALUE>> ret;
+
+    // Remove evicted clients from list
+    mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
+        [&key, &ret] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
+            if (curClientPtr->getKey() == key) {
+                ret = curClientPtr;
+                return true;
+            }
+            return false;
+        }), mClients.end());
+
+    return ret;
+}
+
+template<class KEY, class VALUE>
+void ClientManager<KEY, VALUE>::remove(
+        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value) {
+    Mutex::Autolock lock(mLock);
+    // Remove evicted clients from list
+    mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
+        [&value] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
+            if (curClientPtr == value) {
+                return true;
+            }
+            return false;
+        }), mClients.end());
+}
+
+template<class KEY, class VALUE>
+int64_t ClientManager<KEY, VALUE>::getCurrentCostLocked() const {
+    int64_t totalCost = 0;
+    for (const auto& x : mClients) {
+            totalCost += x->getCost();
+    }
+    return totalCost;
+}
+
+// --------------------------------------------------------------------------------
+
+}; // namespace resource_policy
+}; // namespace android
+
+#endif // ANDROID_SERVICE_UTILS_EVICTION_POLICY_MANAGER_H
diff --git a/services/camera/libcameraservice/utils/RingBuffer.h b/services/camera/libcameraservice/utils/RingBuffer.h
new file mode 100644
index 0000000..df7c00e
--- /dev/null
+++ b/services/camera/libcameraservice/utils/RingBuffer.h
@@ -0,0 +1,361 @@
+/*
+ * 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_SERVICE_UTILS_RING_BUFFER_H
+#define ANDROID_SERVICE_UTILS_RING_BUFFER_H
+
+#include <utils/Log.h>
+#include <cutils/compiler.h>
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+namespace android {
+
+/**
+ * A RingBuffer class that maintains an array of objects that can grow up to a certain size.
+ * Elements added to the RingBuffer are inserted in the logical front of the buffer, and
+ * invalidate all current iterators for that RingBuffer object.
+ */
+template <class T>
+class RingBuffer final {
+public:
+
+    /**
+     * Construct a RingBuffer that can grow up to the given length.
+     */
+    RingBuffer(size_t length);
+
+    /**
+     * Forward iterator to this class.  Implements an std:forward_iterator.
+     */
+    class iterator : public std::iterator<std::forward_iterator_tag, T> {
+    public:
+        iterator(T* ptr, size_t size, size_t pos, size_t ctr);
+
+        iterator& operator++();
+
+        iterator operator++(int);
+
+        bool operator==(const iterator& rhs);
+
+        bool operator!=(const iterator& rhs);
+
+        T& operator*();
+
+        T* operator->();
+
+    private:
+        T* mPtr;
+        size_t mSize;
+        size_t mPos;
+        size_t mCtr;
+    };
+
+    /**
+     * Constant forward iterator to this class.  Implements an std:forward_iterator.
+     */
+    class const_iterator : public std::iterator<std::forward_iterator_tag, T> {
+    public:
+        const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr);
+
+        const_iterator& operator++();
+
+        const_iterator operator++(int);
+
+        bool operator==(const const_iterator& rhs);
+
+        bool operator!=(const const_iterator& rhs);
+
+        const T& operator*();
+
+        const T* operator->();
+
+    private:
+        const T* mPtr;
+        size_t mSize;
+        size_t mPos;
+        size_t mCtr;
+    };
+
+    /**
+     * Adds item to the front of this RingBuffer.  If the RingBuffer is at its maximum length,
+     * this will result in the last element being replaced (this is done using the element's
+     * assignment operator).
+     *
+     * All current iterators are invalidated.
+     */
+    void add(const T& item);
+
+    /**
+     * Moves item to the front of this RingBuffer.  Following a call to this, item should no
+     * longer be used.  If the RingBuffer is at its maximum length, this will result in the
+     * last element being replaced (this is done using the element's assignment operator).
+     *
+     * All current iterators are invalidated.
+     */
+    void add(T&& item);
+
+    /**
+     * Construct item in-place in the front of this RingBuffer using the given arguments.  If
+     * the RingBuffer is at its maximum length, this will result in the last element being
+     * replaced (this is done using the element's assignment operator).
+     *
+     * All current iterators are invalidated.
+     */
+    template <class... Args>
+    void emplace(Args&&... args);
+
+    /**
+     * Get an iterator to the front of this RingBuffer.
+     */
+    iterator begin();
+
+    /**
+     * Get an iterator to the end of this RingBuffer.
+     */
+    iterator end();
+
+    /**
+     * Get a const_iterator to the front of this RingBuffer.
+     */
+    const_iterator begin() const;
+
+    /**
+     * Get a const_iterator to the end of this RingBuffer.
+     */
+    const_iterator end() const;
+
+    /**
+     * Return a reference to the element at a given index.  If the index is out of range for
+     * this ringbuffer, [0, size), the behavior for this is undefined.
+     */
+    T& operator[](size_t index);
+
+    /**
+     * Return a const reference to the element at a given index.  If the index is out of range
+     * for this ringbuffer, [0, size), the behavior for this is undefined.
+     */
+    const T& operator[](size_t index) const;
+
+    /**
+     * Return the current size of this RingBuffer.
+     */
+    size_t size() const;
+
+    /**
+     * Remove all elements from this RingBuffer and set the size to 0.
+     */
+    void clear();
+
+private:
+    size_t mFrontIdx;
+    size_t mMaxBufferSize;
+    std::vector<T> mBuffer;
+}; // class RingBuffer
+
+
+template <class T>
+RingBuffer<T>::RingBuffer(size_t length) : mFrontIdx{0}, mMaxBufferSize{length} {}
+
+template <class T>
+RingBuffer<T>::iterator::iterator(T* ptr, size_t size, size_t pos, size_t ctr) :
+        mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {}
+
+template <class T>
+typename RingBuffer<T>::iterator& RingBuffer<T>::iterator::operator++() {
+    ++mCtr;
+
+    if (CC_UNLIKELY(mCtr == mSize)) {
+        mPos = mSize;
+        return *this;
+    }
+
+    mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1);
+    return *this;
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::iterator::operator++(int) {
+    iterator tmp{mPtr, mSize, mPos, mCtr};
+    ++(*this);
+    return tmp;
+}
+
+template <class T>
+bool RingBuffer<T>::iterator::operator==(const iterator& rhs) {
+    return (mPtr + mPos) == (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+bool RingBuffer<T>::iterator::operator!=(const iterator& rhs) {
+    return (mPtr + mPos) != (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+T& RingBuffer<T>::iterator::operator*() {
+    return *(mPtr + mPos);
+}
+
+template <class T>
+T* RingBuffer<T>::iterator::operator->() {
+    return mPtr + mPos;
+}
+
+template <class T>
+RingBuffer<T>::const_iterator::const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr) :
+        mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {}
+
+template <class T>
+typename RingBuffer<T>::const_iterator& RingBuffer<T>::const_iterator::operator++() {
+    ++mCtr;
+
+    if (CC_UNLIKELY(mCtr == mSize)) {
+        mPos = mSize;
+        return *this;
+    }
+
+    mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1);
+    return *this;
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::const_iterator::operator++(int) {
+    const_iterator tmp{mPtr, mSize, mPos, mCtr};
+    ++(*this);
+    return tmp;
+}
+
+template <class T>
+bool RingBuffer<T>::const_iterator::operator==(const const_iterator& rhs) {
+    return (mPtr + mPos) == (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+bool RingBuffer<T>::const_iterator::operator!=(const const_iterator& rhs) {
+    return (mPtr + mPos) != (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+const T& RingBuffer<T>::const_iterator::operator*() {
+    return *(mPtr + mPos);
+}
+
+template <class T>
+const T* RingBuffer<T>::const_iterator::operator->() {
+    return mPtr + mPos;
+}
+
+template <class T>
+void RingBuffer<T>::add(const T& item) {
+    if (mBuffer.size() < mMaxBufferSize) {
+        mBuffer.push_back(item);
+        mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+        return;
+    }
+
+    mBuffer[mFrontIdx] = item;
+    mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+void RingBuffer<T>::add(T&& item) {
+    if (mBuffer.size() != mMaxBufferSize) {
+        mBuffer.push_back(std::forward<T>(item));
+        mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+        return;
+    }
+
+    // Only works for types with move assignment operator
+    mBuffer[mFrontIdx] = std::forward<T>(item);
+    mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+template <class... Args>
+void RingBuffer<T>::emplace(Args&&... args) {
+    if (mBuffer.size() != mMaxBufferSize) {
+        mBuffer.emplace_back(std::forward<Args>(args)...);
+        mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+        return;
+    }
+
+    // Only works for types with move assignment operator
+    mBuffer[mFrontIdx] = T(std::forward<Args>(args)...);
+    mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::begin() {
+    size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1;
+    return iterator(mBuffer.data(), mBuffer.size(), (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0);
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::end() {
+    size_t s = mBuffer.size();
+    return iterator(mBuffer.data(), s, s, s);
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::begin() const {
+    size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1;
+    return const_iterator(mBuffer.data(), mBuffer.size(),
+            (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0);
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::end() const {
+    size_t s = mBuffer.size();
+    return const_iterator(mBuffer.data(), s, s, s);
+}
+
+template <class T>
+T& RingBuffer<T>::operator[](size_t index) {
+    LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.",
+            index, mBuffer.size());
+    size_t pos = (index >= mFrontIdx) ?
+            mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index;
+    return mBuffer[pos];
+}
+
+template <class T>
+const T& RingBuffer<T>::operator[](size_t index) const {
+    LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.",
+            index, mBuffer.size());
+    size_t pos = (index >= mFrontIdx) ?
+            mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index;
+    return mBuffer[pos];
+}
+
+template <class T>
+size_t RingBuffer<T>::size() const {
+    return mBuffer.size();
+}
+
+template <class T>
+void RingBuffer<T>::clear() {
+    mBuffer.clear();
+    mFrontIdx = 0;
+}
+
+}; // namespace android
+
+#endif // ANDROID_SERVICE_UTILS_RING_BUFFER_H
+
+
diff --git a/services/medialog/Android.mk b/services/medialog/Android.mk
index 95f2fef..03438bf 100644
--- a/services/medialog/Android.mk
+++ b/services/medialog/Android.mk
@@ -10,4 +10,6 @@
 
 LOCAL_32_BIT_ONLY := true
 
+LOCAL_C_INCLUDES := $(call include-path-for, audio-utils)
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/radio/Android.mk b/services/radio/Android.mk
new file mode 100644
index 0000000..9ee5666
--- /dev/null
+++ b/services/radio/Android.mk
@@ -0,0 +1,36 @@
+# Copyright 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+
+LOCAL_SRC_FILES:=               \
+    RadioService.cpp
+
+LOCAL_SHARED_LIBRARIES:= \
+    libui \
+    liblog \
+    libutils \
+    libbinder \
+    libcutils \
+    libmedia \
+    libhardware \
+    libradio \
+    libradio_metadata
+
+LOCAL_MODULE:= libradioservice
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/radio/RadioRegions.h b/services/radio/RadioRegions.h
new file mode 100644
index 0000000..3335b8a
--- /dev/null
+++ b/services/radio/RadioRegions.h
@@ -0,0 +1,225 @@
+/*
+ * 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_HARDWARE_RADIO_REGIONS_H
+#define ANDROID_HARDWARE_RADIO_REGIONS_H
+
+namespace android {
+
+#define RADIO_BAND_LOWER_FM_ITU1    87500
+#define RADIO_BAND_UPPER_FM_ITU1    108000
+#define RADIO_BAND_SPACING_FM_ITU1  100
+
+#define RADIO_BAND_LOWER_FM_ITU2    87900
+#define RADIO_BAND_UPPER_FM_ITU2    107900
+#define RADIO_BAND_SPACING_FM_ITU2  200
+
+#define RADIO_BAND_LOWER_FM_JAPAN    76000
+#define RADIO_BAND_UPPER_FM_JAPAN    90000
+#define RADIO_BAND_SPACING_FM_JAPAN  100
+
+#define RADIO_BAND_LOWER_FM_OIRT    65800
+#define RADIO_BAND_UPPER_FM_OIRT    74000
+#define RADIO_BAND_SPACING_FM_OIRT  10
+
+#define RADIO_BAND_LOWER_LW         153
+#define RADIO_BAND_UPPER_LW         279
+#define RADIO_BAND_SPACING_LW       9
+
+#define RADIO_BAND_LOWER_MW_IUT1    531
+#define RADIO_BAND_UPPER_MW_ITU1    1611
+#define RADIO_BAND_SPACING_MW_ITU1  9
+
+#define RADIO_BAND_LOWER_MW_IUT2    540
+#define RADIO_BAND_UPPER_MW_ITU2    1610
+#define RADIO_BAND_SPACING_MW_ITU2  10
+
+#define RADIO_BAND_LOWER_SW         2300
+#define RADIO_BAND_UPPER_SW         26100
+#define RADIO_BAND_SPACING_SW       5
+
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+const radio_band_config_t sKnownRegionConfigs[] = {
+    {   // FM ITU 1
+        RADIO_REGION_ITU_1,
+        {
+        RADIO_BAND_FM,
+            false,
+            RADIO_BAND_LOWER_FM_ITU1,
+            RADIO_BAND_UPPER_FM_ITU1,
+            1,
+            {RADIO_BAND_SPACING_FM_ITU1},
+            {
+            RADIO_DEEMPHASIS_50,
+            true,
+            RADIO_RDS_WORLD,
+            true,
+            true,
+            }
+        }
+    },
+    {   // FM Americas
+        RADIO_REGION_ITU_2,
+        {
+        RADIO_BAND_FM,
+            false,
+            RADIO_BAND_LOWER_FM_ITU2,
+            RADIO_BAND_UPPER_FM_ITU2,
+            1,
+            {RADIO_BAND_SPACING_FM_ITU2},
+            {
+            RADIO_DEEMPHASIS_75,
+            true,
+            RADIO_RDS_US,
+            true,
+            true,
+            }
+        }
+    },
+    {   // FM Japan
+        RADIO_REGION_JAPAN,
+        {
+        RADIO_BAND_FM,
+            false,
+            RADIO_BAND_LOWER_FM_JAPAN,
+            RADIO_BAND_UPPER_FM_JAPAN,
+            1,
+            {RADIO_BAND_SPACING_FM_JAPAN},
+            {
+            RADIO_DEEMPHASIS_50,
+            true,
+            RADIO_RDS_WORLD,
+            true,
+            true,
+            }
+        }
+    },
+    {   // FM Korea
+        RADIO_REGION_KOREA,
+        {
+        RADIO_BAND_FM,
+            false,
+            RADIO_BAND_LOWER_FM_ITU1,
+            RADIO_BAND_UPPER_FM_ITU1,
+            1,
+            {RADIO_BAND_SPACING_FM_ITU1},
+            {
+            RADIO_DEEMPHASIS_75,
+            true,
+            RADIO_RDS_WORLD,
+            true,
+            true,
+            }
+        }
+    },
+    {   // FM OIRT
+        RADIO_REGION_OIRT,
+        {
+        RADIO_BAND_FM,
+            false,
+            RADIO_BAND_LOWER_FM_OIRT,
+            RADIO_BAND_UPPER_FM_OIRT,
+            1,
+            {RADIO_BAND_SPACING_FM_OIRT},
+            {
+            RADIO_DEEMPHASIS_50,
+            true,
+            RADIO_RDS_WORLD,
+            true,
+            true,
+            }
+        }
+    },
+    {   // FM US HD radio
+        RADIO_REGION_ITU_2,
+        {
+            RADIO_BAND_FM_HD,
+            false,
+            RADIO_BAND_LOWER_FM_ITU2,
+            RADIO_BAND_UPPER_FM_ITU2,
+            1,
+            {RADIO_BAND_SPACING_FM_ITU2},
+            {
+            RADIO_DEEMPHASIS_75,
+            true,
+            RADIO_RDS_US,
+            true,
+            true,
+            }
+        }
+    },
+    {   // AM LW
+        RADIO_REGION_ITU_1,
+        {
+            RADIO_BAND_AM,
+            false,
+            RADIO_BAND_LOWER_LW,
+            RADIO_BAND_UPPER_LW,
+            1,
+            {RADIO_BAND_SPACING_LW},
+            {
+            }
+        }
+    },
+    {   // AM SW
+        RADIO_REGION_ITU_1,
+        {
+            RADIO_BAND_AM,
+            false,
+            RADIO_BAND_LOWER_SW,
+            RADIO_BAND_UPPER_SW,
+            1,
+            {RADIO_BAND_SPACING_SW},
+            {
+            }
+        }
+    },
+    {   // AM MW ITU1
+        RADIO_REGION_ITU_1,
+        {
+            RADIO_BAND_AM,
+            false,
+            RADIO_BAND_LOWER_MW_IUT1,
+            RADIO_BAND_UPPER_MW_ITU1,
+            1,
+            {RADIO_BAND_SPACING_MW_ITU1},
+            {
+            }
+        }
+    },
+    {   // AM MW ITU2
+        RADIO_REGION_ITU_2,
+        {
+            RADIO_BAND_AM,
+            false,
+            RADIO_BAND_LOWER_MW_IUT2,
+            RADIO_BAND_UPPER_MW_ITU2,
+            1,
+            {RADIO_BAND_SPACING_MW_ITU2},
+            {
+            }
+        }
+    }
+};
+
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_RADIO_REGIONS_H
diff --git a/services/radio/RadioService.cpp b/services/radio/RadioService.cpp
new file mode 100644
index 0000000..a6c2bdf
--- /dev/null
+++ b/services/radio/RadioService.cpp
@@ -0,0 +1,901 @@
+/*
+ * 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 "RadioService"
+//#define LOG_NDEBUG 0
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pthread.h>
+
+#include <system/audio.h>
+#include <system/audio_policy.h>
+#include <system/radio.h>
+#include <system/radio_metadata.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+#include <hardware/hardware.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <hardware/radio.h>
+#include <media/AudioSystem.h>
+#include "RadioService.h"
+#include "RadioRegions.h"
+
+namespace android {
+
+static const char kRadioTunerAudioDeviceName[] = "Radio tuner source";
+
+RadioService::RadioService()
+    : BnRadioService(), mNextUniqueId(1)
+{
+    ALOGI("%s", __FUNCTION__);
+}
+
+void RadioService::onFirstRef()
+{
+    const hw_module_t *mod;
+    int rc;
+    struct radio_hw_device *dev;
+
+    ALOGI("%s", __FUNCTION__);
+
+    rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, RADIO_HARDWARE_MODULE_ID_FM, &mod);
+    if (rc != 0) {
+        ALOGE("couldn't load radio module %s.%s (%s)",
+              RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
+        return;
+    }
+    rc = radio_hw_device_open(mod, &dev);
+    if (rc != 0) {
+        ALOGE("couldn't open radio hw device in %s.%s (%s)",
+              RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
+        return;
+    }
+    if (dev->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
+        ALOGE("wrong radio hw device version %04x", dev->common.version);
+        return;
+    }
+
+    struct radio_hal_properties halProperties;
+    rc = dev->get_properties(dev, &halProperties);
+    if (rc != 0) {
+        ALOGE("could not read implementation properties");
+        return;
+    }
+
+    radio_properties_t properties;
+    properties.handle =
+            (radio_handle_t)android_atomic_inc(&mNextUniqueId);
+
+    ALOGI("loaded default module %s, handle %d", properties.product, properties.handle);
+
+    convertProperties(&properties, &halProperties);
+    sp<Module> module = new Module(dev, properties);
+    mModules.add(properties.handle, module);
+}
+
+RadioService::~RadioService()
+{
+    for (size_t i = 0; i < mModules.size(); i++) {
+        radio_hw_device_close(mModules.valueAt(i)->hwDevice());
+    }
+}
+
+status_t RadioService::listModules(struct radio_properties *properties,
+                             uint32_t *numModules)
+{
+    ALOGV("listModules");
+
+    AutoMutex lock(mServiceLock);
+    if (numModules == NULL || (*numModules != 0 && properties == NULL)) {
+        return BAD_VALUE;
+    }
+    size_t maxModules = *numModules;
+    *numModules = mModules.size();
+    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
+        properties[i] = mModules.valueAt(i)->properties();
+    }
+    return NO_ERROR;
+}
+
+status_t RadioService::attach(radio_handle_t handle,
+                        const sp<IRadioClient>& client,
+                        const struct radio_band_config *config,
+                        bool withAudio,
+                        sp<IRadio>& radio)
+{
+    ALOGV("%s %d config %p withAudio %d", __FUNCTION__, handle, config, withAudio);
+
+    AutoMutex lock(mServiceLock);
+    radio.clear();
+    if (client == 0) {
+        return BAD_VALUE;
+    }
+    ssize_t index = mModules.indexOfKey(handle);
+    if (index < 0) {
+        return BAD_VALUE;
+    }
+    sp<Module> module = mModules.valueAt(index);
+
+    if (config == NULL) {
+        config = module->getDefaultConfig();
+        if (config == NULL) {
+            return INVALID_OPERATION;
+        }
+    }
+    ALOGV("%s region %d type %d", __FUNCTION__, config->region, config->band.type);
+
+    radio = module->addClient(client, config, withAudio);
+
+    if (radio == 0) {
+        NO_INIT;
+    }
+    return NO_ERROR;
+}
+
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 60000;
+
+static bool tryLock(Mutex& mutex)
+{
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
+status_t RadioService::dump(int fd, const Vector<String16>& args __unused) {
+    String8 result;
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        result.appendFormat("Permission Denial: can't dump RadioService");
+        write(fd, result.string(), result.size());
+    } else {
+        bool locked = tryLock(mServiceLock);
+        // failed to lock - RadioService is probably deadlocked
+        if (!locked) {
+            result.append("RadioService may be deadlocked\n");
+            write(fd, result.string(), result.size());
+        }
+
+        if (locked) mServiceLock.unlock();
+    }
+    return NO_ERROR;
+}
+
+status_t RadioService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    return BnRadioService::onTransact(code, data, reply, flags);
+}
+
+
+// static
+void RadioService::callback(radio_hal_event_t *halEvent, void *cookie)
+{
+    CallbackThread *callbackThread = (CallbackThread *)cookie;
+    if (callbackThread == NULL) {
+        return;
+    }
+    callbackThread->sendEvent(halEvent);
+}
+
+/* static */
+void RadioService::convertProperties(radio_properties_t *properties,
+                                     const radio_hal_properties_t *halProperties)
+{
+    memset(properties, 0, sizeof(struct radio_properties));
+    properties->class_id = halProperties->class_id;
+    strlcpy(properties->implementor, halProperties->implementor,
+            RADIO_STRING_LEN_MAX);
+    strlcpy(properties->product, halProperties->product,
+            RADIO_STRING_LEN_MAX);
+    strlcpy(properties->version, halProperties->version,
+            RADIO_STRING_LEN_MAX);
+    strlcpy(properties->serial, halProperties->serial,
+            RADIO_STRING_LEN_MAX);
+    properties->num_tuners = halProperties->num_tuners;
+    properties->num_audio_sources = halProperties->num_audio_sources;
+    properties->supports_capture = halProperties->supports_capture;
+
+    for (size_t i = 0; i < ARRAY_SIZE(sKnownRegionConfigs); i++) {
+        const radio_hal_band_config_t *band = &sKnownRegionConfigs[i].band;
+        size_t j;
+        for (j = 0; j < halProperties->num_bands; j++) {
+            const radio_hal_band_config_t *halBand = &halProperties->bands[j];
+            size_t k;
+            if (band->type != halBand->type) continue;
+            if (band->lower_limit < halBand->lower_limit) continue;
+            if (band->upper_limit > halBand->upper_limit) continue;
+            for (k = 0; k < halBand->num_spacings; k++) {
+                if (band->spacings[0] == halBand->spacings[k]) break;
+            }
+            if (k == halBand->num_spacings) continue;
+            if (band->type == RADIO_BAND_AM) break;
+            if ((band->fm.deemphasis & halBand->fm.deemphasis) == 0) continue;
+            if (halBand->fm.rds == 0) break;
+            if ((band->fm.rds & halBand->fm.rds) != 0) break;
+        }
+        if (j == halProperties->num_bands) continue;
+
+        ALOGI("convertProperties() Adding band type %d region %d",
+              sKnownRegionConfigs[i].band.type , sKnownRegionConfigs[i].region);
+
+        memcpy(&properties->bands[properties->num_bands++],
+               &sKnownRegionConfigs[i],
+               sizeof(radio_band_config_t));
+    }
+}
+
+#undef LOG_TAG
+#define LOG_TAG "RadioService::CallbackThread"
+
+RadioService::CallbackThread::CallbackThread(const wp<ModuleClient>& moduleClient)
+    : mModuleClient(moduleClient), mMemoryDealer(new MemoryDealer(1024 * 1024, "RadioService"))
+{
+}
+
+RadioService::CallbackThread::~CallbackThread()
+{
+    mEventQueue.clear();
+}
+
+void RadioService::CallbackThread::onFirstRef()
+{
+    run("RadioService cbk", ANDROID_PRIORITY_URGENT_AUDIO);
+}
+
+bool RadioService::CallbackThread::threadLoop()
+{
+    while (!exitPending()) {
+        sp<IMemory> eventMemory;
+        sp<ModuleClient> moduleClient;
+        {
+            Mutex::Autolock _l(mCallbackLock);
+            while (mEventQueue.isEmpty() && !exitPending()) {
+                ALOGV("CallbackThread::threadLoop() sleep");
+                mCallbackCond.wait(mCallbackLock);
+                ALOGV("CallbackThread::threadLoop() wake up");
+            }
+            if (exitPending()) {
+                break;
+            }
+            eventMemory = mEventQueue[0];
+            mEventQueue.removeAt(0);
+            moduleClient = mModuleClient.promote();
+        }
+        if (moduleClient != 0) {
+            moduleClient->onCallbackEvent(eventMemory);
+            eventMemory.clear();
+        }
+    }
+    return false;
+}
+
+void RadioService::CallbackThread::exit()
+{
+    Mutex::Autolock _l(mCallbackLock);
+    requestExit();
+    mCallbackCond.broadcast();
+}
+
+sp<IMemory> RadioService::CallbackThread::prepareEvent(radio_hal_event_t *halEvent)
+{
+    sp<IMemory> eventMemory;
+
+    size_t headerSize =
+            (sizeof(struct radio_event) + sizeof(unsigned int) - 1) /sizeof(unsigned int);
+    size_t metadataSize = 0;
+    switch (halEvent->type) {
+    case RADIO_EVENT_TUNED:
+    case RADIO_EVENT_AF_SWITCH:
+        if (radio_metadata_check(halEvent->info.metadata) == 0) {
+            metadataSize = radio_metadata_get_size(halEvent->info.metadata);
+        }
+        break;
+    case RADIO_EVENT_METADATA:
+        if (radio_metadata_check(halEvent->metadata) != 0) {
+            return eventMemory;
+        }
+        metadataSize = radio_metadata_get_size(halEvent->metadata);
+        break;
+    default:
+        break;
+    }
+    size_t size = headerSize + metadataSize;
+    eventMemory = mMemoryDealer->allocate(size);
+    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+        eventMemory.clear();
+        return eventMemory;
+    }
+    struct radio_event *event = (struct radio_event *)eventMemory->pointer();
+    event->type = halEvent->type;
+    event->status = halEvent->status;
+
+    switch (event->type) {
+    case RADIO_EVENT_CONFIG:
+        event->config.band = halEvent->config;
+        break;
+    case RADIO_EVENT_TUNED:
+    case RADIO_EVENT_AF_SWITCH:
+        event->info = halEvent->info;
+        if (metadataSize != 0) {
+            memcpy((char *)event + headerSize, halEvent->info.metadata, metadataSize);
+            // replace meta data pointer by offset while in shared memory so that receiving side
+            // can restore the pointer in destination process.
+            event->info.metadata = (radio_metadata_t *)headerSize;
+        }
+        break;
+    case RADIO_EVENT_TA:
+    case RADIO_EVENT_ANTENNA:
+    case RADIO_EVENT_CONTROL:
+        event->on = halEvent->on;
+        break;
+    case RADIO_EVENT_METADATA:
+        memcpy((char *)event + headerSize, halEvent->metadata, metadataSize);
+        // replace meta data pointer by offset while in shared memory so that receiving side
+        // can restore the pointer in destination process.
+        event->metadata = (radio_metadata_t *)headerSize;
+        break;
+    case RADIO_EVENT_HW_FAILURE:
+    default:
+        break;
+    }
+
+    return eventMemory;
+}
+
+void RadioService::CallbackThread::sendEvent(radio_hal_event_t *event)
+ {
+     sp<IMemory> eventMemory = prepareEvent(event);
+     if (eventMemory == 0) {
+         return;
+     }
+
+     AutoMutex lock(mCallbackLock);
+     mEventQueue.add(eventMemory);
+     mCallbackCond.signal();
+     ALOGV("%s DONE", __FUNCTION__);
+}
+
+
+#undef LOG_TAG
+#define LOG_TAG "RadioService::Module"
+
+RadioService::Module::Module(radio_hw_device* hwDevice, radio_properties properties)
+ : mHwDevice(hwDevice), mProperties(properties), mMute(true)
+{
+}
+
+RadioService::Module::~Module() {
+    mModuleClients.clear();
+}
+
+status_t RadioService::Module::dump(int fd __unused, const Vector<String16>& args __unused) {
+    String8 result;
+    return NO_ERROR;
+}
+
+sp<RadioService::ModuleClient> RadioService::Module::addClient(const sp<IRadioClient>& client,
+                                    const struct radio_band_config *config,
+                                    bool audio)
+{
+    ALOGV("addClient() %p config %p product %s", this, config, mProperties.product);
+    AutoMutex lock(mLock);
+    sp<ModuleClient> moduleClient;
+    int ret;
+
+    for (size_t i = 0; i < mModuleClients.size(); i++) {
+        if (mModuleClients[i]->client() == client) {
+            // client already connected: reject
+            return moduleClient;
+        }
+    }
+    moduleClient = new ModuleClient(this, client, config, audio);
+
+    struct radio_hal_band_config halConfig;
+    halConfig = config->band;
+
+    // Tuner preemption logic:
+    // There is a limited amount of tuners and a limited amount of radio audio sources per module.
+    // The minimum is one tuner and one audio source.
+    // The numbers of tuners and sources are indicated in the module properties.
+    // NOTE: current framework implementation only supports one radio audio source.
+    // It is possible to open more than one tuner at a time but only one tuner can be connected
+    // to the radio audio source (AUDIO_DEVICE_IN_FM_TUNER).
+    // The base rule is that a newly connected tuner always wins, i.e. always gets a tuner
+    // and can use the audio source if requested.
+    // If another client is preempted, it is notified by a callback with RADIO_EVENT_CONTROL
+    // indicating loss of control.
+    // - If the newly connected client requests the audio source (audio == true):
+    //    - if an audio source is available
+    //          no problem
+    //    - if not:
+    //          the oldest client in the list using audio is preempted.
+    // - If the newly connected client does not request the audio source (audio == false):
+    //    - if a tuner is available
+    //          no problem
+    //    - if not:
+    //          The oldest client not using audio is preempted first and if none is found the
+    //          the oldest client using audio is preempted.
+    // Each time a tuner using the audio source is opened or closed, the audio policy manager is
+    // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
+
+    sp<ModuleClient> oldestTuner;
+    sp<ModuleClient> oldestAudio;
+    size_t allocatedTuners = 0;
+    size_t allocatedAudio = 0;
+    for (size_t i = 0; i < mModuleClients.size(); i++) {
+        if (mModuleClients[i]->getTuner() != NULL) {
+            if (mModuleClients[i]->audio()) {
+                if (oldestAudio == 0) {
+                    oldestAudio = mModuleClients[i];
+                }
+                allocatedAudio++;
+            } else {
+                if (oldestTuner == 0) {
+                    oldestTuner = mModuleClients[i];
+                }
+                allocatedTuners++;
+            }
+        }
+    }
+
+    const struct radio_tuner *halTuner;
+    sp<ModuleClient> preemtedClient;
+    if (audio) {
+        if (allocatedAudio >= mProperties.num_audio_sources) {
+            ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
+            preemtedClient = oldestAudio;
+        }
+    } else {
+        if (allocatedAudio + allocatedTuners >= mProperties.num_tuners) {
+            if (allocatedTuners != 0) {
+                ALOG_ASSERT(oldestTuner != 0, "addClient() allocatedTuners/oldestTuner mismatch");
+                preemtedClient = oldestTuner;
+            } else {
+                ALOG_ASSERT(oldestAudio != 0, "addClient() allocatedAudio/oldestAudio mismatch");
+                preemtedClient = oldestAudio;
+            }
+        }
+    }
+    if (preemtedClient != 0) {
+        halTuner = preemtedClient->getTuner();
+        preemtedClient->setTuner(NULL);
+        mHwDevice->close_tuner(mHwDevice, halTuner);
+        if (preemtedClient->audio()) {
+            notifyDeviceConnection(false, "");
+        }
+    }
+
+    ret = mHwDevice->open_tuner(mHwDevice, &halConfig, audio,
+                                RadioService::callback, moduleClient->callbackThread().get(),
+                                &halTuner);
+    if (ret == 0) {
+        ALOGV("addClient() setTuner %p", halTuner);
+        moduleClient->setTuner(halTuner);
+        mModuleClients.add(moduleClient);
+        if (audio) {
+            notifyDeviceConnection(true, "");
+        }
+    } else {
+        moduleClient.clear();
+    }
+
+
+    ALOGV("addClient() DONE moduleClient %p", moduleClient.get());
+
+    return moduleClient;
+}
+
+void RadioService::Module::removeClient(const sp<ModuleClient>& moduleClient) {
+    ALOGV("removeClient()");
+    AutoMutex lock(mLock);
+    int ret;
+    ssize_t index = -1;
+
+    for (size_t i = 0; i < mModuleClients.size(); i++) {
+        if (mModuleClients[i] == moduleClient) {
+            index = i;
+            break;
+        }
+    }
+    if (index == -1) {
+        return;
+    }
+
+    mModuleClients.removeAt(index);
+    const struct radio_tuner *halTuner = moduleClient->getTuner();
+    if (halTuner == NULL) {
+        return;
+    }
+
+    mHwDevice->close_tuner(mHwDevice, halTuner);
+    if (moduleClient->audio()) {
+        notifyDeviceConnection(false, "");
+    }
+
+    mMute = true;
+
+    if (mModuleClients.isEmpty()) {
+        return;
+    }
+
+    // Tuner reallocation logic:
+    // When a client is removed and was controlling a tuner, this tuner will be allocated to a
+    // previously preempted client. This client will be notified by a callback with
+    // RADIO_EVENT_CONTROL indicating gain of control.
+    // - If a preempted client is waiting for an audio source and one becomes available:
+    //    Allocate the tuner to the most recently added client waiting for an audio source
+    // - If not:
+    //    Allocate the tuner to the most recently added client.
+    // Each time a tuner using the audio source is opened or closed, the audio policy manager is
+    // notified of the connection or disconnection of AUDIO_DEVICE_IN_FM_TUNER.
+
+    sp<ModuleClient> youngestClient;
+    sp<ModuleClient> youngestClientAudio;
+    size_t allocatedTuners = 0;
+    size_t allocatedAudio = 0;
+    for (ssize_t i = mModuleClients.size() - 1; i >= 0; i--) {
+        if (mModuleClients[i]->getTuner() == NULL) {
+            if (mModuleClients[i]->audio()) {
+                if (youngestClientAudio == 0) {
+                    youngestClientAudio = mModuleClients[i];
+                }
+            } else {
+                if (youngestClient == 0) {
+                    youngestClient = mModuleClients[i];
+                }
+            }
+        } else {
+            if (mModuleClients[i]->audio()) {
+                allocatedAudio++;
+            } else {
+                allocatedTuners++;
+            }
+        }
+    }
+
+    ALOG_ASSERT(allocatedTuners + allocatedAudio < mProperties.num_tuners,
+                "removeClient() removed client but no tuner available");
+
+    ALOG_ASSERT(!moduleClient->audio() || allocatedAudio < mProperties.num_audio_sources,
+                "removeClient() removed audio client but no tuner with audio available");
+
+    if (allocatedAudio < mProperties.num_audio_sources && youngestClientAudio != 0) {
+        youngestClient = youngestClientAudio;
+    }
+
+    ALOG_ASSERT(youngestClient != 0, "removeClient() removed client no candidate found for tuner");
+
+    struct radio_hal_band_config halConfig = youngestClient->halConfig();
+    ret = mHwDevice->open_tuner(mHwDevice, &halConfig, youngestClient->audio(),
+                                RadioService::callback, moduleClient->callbackThread().get(),
+                                &halTuner);
+
+    if (ret == 0) {
+        youngestClient->setTuner(halTuner);
+        if (youngestClient->audio()) {
+            notifyDeviceConnection(true, "");
+        }
+    }
+}
+
+status_t RadioService::Module::setMute(bool mute)
+{
+    Mutex::Autolock _l(mLock);
+    if (mute != mMute) {
+        mMute = mute;
+        //TODO notifify audio policy manager of media activity on radio audio device
+    }
+    return NO_ERROR;
+}
+
+status_t RadioService::Module::getMute(bool *mute)
+{
+    Mutex::Autolock _l(mLock);
+    *mute = mMute;
+    return NO_ERROR;
+}
+
+
+const struct radio_band_config *RadioService::Module::getDefaultConfig() const
+{
+    if (mProperties.num_bands == 0) {
+        return NULL;
+    }
+    return &mProperties.bands[0];
+}
+
+void RadioService::Module::notifyDeviceConnection(bool connected,
+                                                  const char *address) {
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
+                                          connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE :
+                                                  AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                                          address, kRadioTunerAudioDeviceName);
+    IPCThreadState::self()->restoreCallingIdentity(token);
+}
+
+#undef LOG_TAG
+#define LOG_TAG "RadioService::ModuleClient"
+
+RadioService::ModuleClient::ModuleClient(const sp<Module>& module,
+                                         const sp<IRadioClient>& client,
+                                         const struct radio_band_config *config,
+                                         bool audio)
+ : mModule(module), mClient(client), mConfig(*config), mAudio(audio), mTuner(NULL)
+{
+}
+
+void RadioService::ModuleClient::onFirstRef()
+{
+    mCallbackThread = new CallbackThread(this);
+    IInterface::asBinder(mClient)->linkToDeath(this);
+}
+
+RadioService::ModuleClient::~ModuleClient() {
+    if (mClient != 0) {
+        IInterface::asBinder(mClient)->unlinkToDeath(this);
+        mClient.clear();
+    }
+    if (mCallbackThread != 0) {
+        mCallbackThread->exit();
+    }
+}
+
+status_t RadioService::ModuleClient::dump(int fd __unused,
+                                             const Vector<String16>& args __unused) {
+    String8 result;
+    return NO_ERROR;
+}
+
+void RadioService::ModuleClient::detach() {
+    ALOGV("%s", __FUNCTION__);
+    sp<ModuleClient> strongMe = this;
+    {
+        AutoMutex lock(mLock);
+        if (mClient != 0) {
+            IInterface::asBinder(mClient)->unlinkToDeath(this);
+            mClient.clear();
+        }
+    }
+    sp<Module> module = mModule.promote();
+    if (module == 0) {
+        return;
+    }
+    module->removeClient(this);
+}
+
+radio_hal_band_config_t RadioService::ModuleClient::halConfig() const
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    return mConfig.band;
+}
+
+const struct radio_tuner *RadioService::ModuleClient::getTuner() const
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    return mTuner;
+}
+
+void RadioService::ModuleClient::setTuner(const struct radio_tuner *tuner)
+{
+    ALOGV("%s %p", __FUNCTION__, this);
+
+    AutoMutex lock(mLock);
+    mTuner = tuner;
+    ALOGV("%s locked", __FUNCTION__);
+
+    radio_hal_event_t event;
+    event.type = RADIO_EVENT_CONTROL;
+    event.status = 0;
+    event.on = mTuner != NULL;
+    mCallbackThread->sendEvent(&event);
+    ALOGV("%s DONE", __FUNCTION__);
+
+}
+
+status_t RadioService::ModuleClient::setConfiguration(const struct radio_band_config *config)
+{
+    AutoMutex lock(mLock);
+    status_t status = NO_ERROR;
+    ALOGV("%s locked", __FUNCTION__);
+
+    if (mTuner != NULL) {
+        struct radio_hal_band_config halConfig;
+        halConfig = config->band;
+        status = (status_t)mTuner->set_configuration(mTuner, &halConfig);
+        if (status == NO_ERROR) {
+            mConfig = *config;
+        }
+    } else {
+        mConfig = *config;
+        status == INVALID_OPERATION;
+    }
+
+    return status;
+}
+
+status_t RadioService::ModuleClient::getConfiguration(struct radio_band_config *config)
+{
+    AutoMutex lock(mLock);
+    status_t status = NO_ERROR;
+    ALOGV("%s locked", __FUNCTION__);
+
+    if (mTuner != NULL) {
+        struct radio_hal_band_config halConfig;
+        status = (status_t)mTuner->get_configuration(mTuner, &halConfig);
+        if (status == NO_ERROR) {
+            mConfig.band = halConfig;
+        }
+    }
+    *config = mConfig;
+
+    return status;
+}
+
+status_t RadioService::ModuleClient::setMute(bool mute)
+{
+    sp<Module> module;
+    {
+        Mutex::Autolock _l(mLock);
+        ALOGV("%s locked", __FUNCTION__);
+        if (mTuner == NULL || !mAudio) {
+            return INVALID_OPERATION;
+        }
+        module = mModule.promote();
+        if (module == 0) {
+            return NO_INIT;
+        }
+    }
+    module->setMute(mute);
+    return NO_ERROR;
+}
+
+status_t RadioService::ModuleClient::getMute(bool *mute)
+{
+    sp<Module> module;
+    {
+        Mutex::Autolock _l(mLock);
+        ALOGV("%s locked", __FUNCTION__);
+        module = mModule.promote();
+        if (module == 0) {
+            return NO_INIT;
+        }
+    }
+    return module->getMute(mute);
+}
+
+status_t RadioService::ModuleClient::scan(radio_direction_t direction, bool skipSubChannel)
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    status_t status;
+    if (mTuner != NULL) {
+        status = (status_t)mTuner->scan(mTuner, direction, skipSubChannel);
+    } else {
+        status = INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t RadioService::ModuleClient::step(radio_direction_t direction, bool skipSubChannel)
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    status_t status;
+    if (mTuner != NULL) {
+        status = (status_t)mTuner->step(mTuner, direction, skipSubChannel);
+    } else {
+        status = INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t RadioService::ModuleClient::tune(unsigned int channel, unsigned int subChannel)
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    status_t status;
+    if (mTuner != NULL) {
+        status = (status_t)mTuner->tune(mTuner, channel, subChannel);
+    } else {
+        status = INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t RadioService::ModuleClient::cancel()
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    status_t status;
+    if (mTuner != NULL) {
+        status = (status_t)mTuner->cancel(mTuner);
+    } else {
+        status = INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t RadioService::ModuleClient::getProgramInformation(struct radio_program_info *info)
+{
+    AutoMutex lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    status_t status;
+    if (mTuner != NULL) {
+        status = (status_t)mTuner->get_program_information(mTuner, info);
+    } else {
+        status = INVALID_OPERATION;
+    }
+    return status;
+}
+
+status_t RadioService::ModuleClient::hasControl(bool *hasControl)
+{
+    Mutex::Autolock lock(mLock);
+    ALOGV("%s locked", __FUNCTION__);
+    *hasControl = mTuner != NULL;
+    return NO_ERROR;
+}
+
+void RadioService::ModuleClient::onCallbackEvent(const sp<IMemory>& eventMemory)
+{
+    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+        return;
+    }
+
+    sp<IRadioClient> client;
+    {
+        AutoMutex lock(mLock);
+        ALOGV("%s locked", __FUNCTION__);
+        radio_event_t *event = (radio_event_t *)eventMemory->pointer();
+        switch (event->type) {
+        case RADIO_EVENT_CONFIG:
+            mConfig.band = event->config.band;
+            event->config.region = mConfig.region;
+            break;
+        default:
+            break;
+        }
+
+        client = mClient;
+    }
+    if (client != 0) {
+        client->onEvent(eventMemory);
+    }
+}
+
+
+void RadioService::ModuleClient::binderDied(
+    const wp<IBinder> &who __unused) {
+    ALOGW("client binder died for client %p", this);
+    detach();
+}
+
+}; // namespace android
diff --git a/services/radio/RadioService.h b/services/radio/RadioService.h
new file mode 100644
index 0000000..49feda6
--- /dev/null
+++ b/services/radio/RadioService.h
@@ -0,0 +1,211 @@
+/*
+ * 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_HARDWARE_RADIO_SERVICE_H
+#define ANDROID_HARDWARE_RADIO_SERVICE_H
+
+#include <utils/Vector.h>
+//#include <binder/AppOpsManager.h>
+#include <binder/MemoryDealer.h>
+#include <binder/BinderService.h>
+#include <binder/IAppOpsCallback.h>
+#include <radio/IRadioService.h>
+#include <radio/IRadio.h>
+#include <radio/IRadioClient.h>
+#include <system/radio.h>
+#include <hardware/radio.h>
+
+namespace android {
+
+class MemoryHeapBase;
+
+class RadioService :
+    public BinderService<RadioService>,
+    public BnRadioService
+{
+    friend class BinderService<RadioService>;
+
+public:
+    class ModuleClient;
+    class Module;
+
+    static char const* getServiceName() { return "media.radio"; }
+
+                        RadioService();
+    virtual             ~RadioService();
+
+    // IRadioService
+    virtual status_t listModules(struct radio_properties *properties,
+                                 uint32_t *numModules);
+
+    virtual status_t attach(radio_handle_t handle,
+                            const sp<IRadioClient>& client,
+                            const struct radio_band_config *config,
+                            bool withAudio,
+                            sp<IRadio>& radio);
+
+    virtual status_t    onTransact(uint32_t code, const Parcel& data,
+                                   Parcel* reply, uint32_t flags);
+
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+
+
+    class Module : public virtual RefBase {
+    public:
+
+       Module(radio_hw_device* hwDevice,
+              struct radio_properties properties);
+
+       virtual ~Module();
+
+               sp<ModuleClient> addClient(const sp<IRadioClient>& client,
+                                  const struct radio_band_config *config,
+                                  bool audio);
+
+               void removeClient(const sp<ModuleClient>& moduleClient);
+
+               status_t setMute(bool mute);
+
+               status_t getMute(bool *mute);
+
+       virtual status_t dump(int fd, const Vector<String16>& args);
+
+       const struct radio_hw_device *hwDevice() const { return mHwDevice; }
+       const struct radio_properties properties() const { return mProperties; }
+       const struct radio_band_config *getDefaultConfig() const ;
+
+    private:
+
+       void notifyDeviceConnection(bool connected, const char *address);
+
+        Mutex                         mLock;          // protects  mModuleClients
+        const struct radio_hw_device  *mHwDevice;     // HAL hardware device
+        const struct radio_properties mProperties;    // cached hardware module properties
+        Vector< sp<ModuleClient> >    mModuleClients; // list of attached clients
+        bool                          mMute;          // radio audio source state
+                                                      // when unmuted, audio is routed to the
+                                                      // output device selected for media use case.
+    }; // class Module
+
+    class CallbackThread : public Thread {
+    public:
+
+        CallbackThread(const wp<ModuleClient>& moduleClient);
+
+        virtual ~CallbackThread();
+
+
+        // Thread virtuals
+        virtual bool threadLoop();
+
+        // RefBase
+        virtual void onFirstRef();
+
+                void exit();
+
+                void sendEvent(radio_hal_event_t *halEvent);
+                sp<IMemory> prepareEvent(radio_hal_event_t *halEvent);
+
+    private:
+        wp<ModuleClient>      mModuleClient;    // client module the thread belongs to
+        Condition             mCallbackCond;    // condition signaled when a new event is posted
+        Mutex                 mCallbackLock;    // protects mEventQueue
+        Vector< sp<IMemory> > mEventQueue;      // pending callback events
+        sp<MemoryDealer>      mMemoryDealer;    // shared memory for callback event
+    }; // class CallbackThread
+
+    class ModuleClient : public BnRadio,
+                   public IBinder::DeathRecipient {
+    public:
+
+       ModuleClient(const sp<Module>& module,
+              const sp<IRadioClient>& client,
+              const struct radio_band_config *config,
+              bool audio);
+
+       virtual ~ModuleClient();
+
+       // IRadio
+       virtual void detach();
+
+       virtual status_t setConfiguration(const struct radio_band_config *config);
+
+       virtual status_t getConfiguration(struct radio_band_config *config);
+
+       virtual status_t setMute(bool mute);
+
+       virtual status_t getMute(bool *mute);
+
+       virtual status_t scan(radio_direction_t direction, bool skipSubChannel);
+
+       virtual status_t step(radio_direction_t direction, bool skipSubChannel);
+
+       virtual status_t tune(unsigned int channel, unsigned int subChannel);
+
+       virtual status_t cancel();
+
+       virtual status_t getProgramInformation(struct radio_program_info *info);
+
+       virtual status_t hasControl(bool *hasControl);
+
+       virtual status_t dump(int fd, const Vector<String16>& args);
+
+               sp<IRadioClient> client() const { return mClient; }
+               wp<Module> module() const { return mModule; }
+               radio_hal_band_config_t halConfig() const;
+               sp<CallbackThread> callbackThread() const { return mCallbackThread; }
+               void setTuner(const struct radio_tuner *tuner);
+               const struct radio_tuner *getTuner() const;
+               bool audio() const { return mAudio; }
+
+               void onCallbackEvent(const sp<IMemory>& event);
+
+       virtual void onFirstRef();
+
+
+       // IBinder::DeathRecipient implementation
+       virtual void        binderDied(const wp<IBinder> &who);
+
+    private:
+
+        mutable Mutex               mLock;           // protects mClient, mConfig and mTuner
+        wp<Module>                  mModule;         // The module this client is attached to
+        sp<IRadioClient>            mClient;         // event callback binder interface
+        radio_band_config_t         mConfig;         // current band configuration
+        sp<CallbackThread>          mCallbackThread; // event callback thread
+        const bool                  mAudio;
+        const struct radio_tuner    *mTuner;        // HAL tuner interface. NULL indicates that
+                                                    // this client does not have control on any
+                                                    // tuner
+    }; // class ModuleClient
+
+
+    static void callback(radio_hal_event_t *halEvent, void *cookie);
+
+private:
+
+    virtual void onFirstRef();
+
+    static void convertProperties(radio_properties_t *properties,
+                                  const radio_hal_properties_t *halProperties);
+    Mutex               mServiceLock;   // protects mModules
+    volatile int32_t    mNextUniqueId;  // for module ID allocation
+    DefaultKeyedVector< radio_handle_t, sp<Module> > mModules;
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_RADIO_SERVICE_H
diff --git a/services/soundtrigger/Android.mk b/services/soundtrigger/Android.mk
index 572ae56..ecc49ae 100644
--- a/services/soundtrigger/Android.mk
+++ b/services/soundtrigger/Android.mk
@@ -32,9 +32,7 @@
     libcutils \
     libhardware \
     libsoundtrigger \
-    libmedia
-
-LOCAL_STATIC_LIBRARIES := \
+    libmedia \
     libserviceutility
 
 LOCAL_C_INCLUDES += \
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index b5aaee3..081aff7 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -143,7 +143,7 @@
     sp<Module> module = mModules.valueAt(index);
 
     module->setClient(client);
-    client->asBinder()->linkToDeath(module);
+    IInterface::asBinder(client)->linkToDeath(module);
     moduleInterface = module;
 
     module->setCaptureState_l(mCaptureState);
@@ -510,7 +510,7 @@
         mModels.clear();
     }
     if (mClient != 0) {
-        mClient->asBinder()->unlinkToDeath(this);
+        IInterface::asBinder(mClient)->unlinkToDeath(this);
     }
     sp<SoundTriggerHwService> service = mService.promote();
     if (service == 0) {
@@ -535,6 +535,16 @@
             (struct sound_trigger_sound_model *)modelMemory->pointer();
 
     AutoMutex lock(mLock);
+
+    if (mModels.size() >= mDescriptor.properties.max_sound_models) {
+        if (mModels.size() == 0) {
+            return INVALID_OPERATION;
+        }
+        ALOGW("loadSoundModel() max number of models exceeded %d making room for a new one",
+              mDescriptor.properties.max_sound_models);
+        unloadSoundModel_l(mModels.valueAt(0)->mHandle);
+    }
+
     status_t status = mHwDevice->load_sound_model(mHwDevice,
                                                   sound_model,
                                                   SoundTriggerHwService::soundModelCallback,
@@ -566,6 +576,11 @@
     }
 
     AutoMutex lock(mLock);
+    return unloadSoundModel_l(handle);
+}
+
+status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
+{
     ssize_t index = mModels.indexOfKey(handle);
     if (index < 0) {
         return BAD_VALUE;
@@ -574,6 +589,7 @@
     mModels.removeItem(handle);
     if (model->mState == Model::STATE_ACTIVE) {
         mHwDevice->stop_recognition(mHwDevice, model->mHandle);
+        model->mState = Model::STATE_IDLE;
     }
     AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
     return mHwDevice->unload_sound_model(mHwDevice, handle);
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
index d05dacd..2619a5f 100644
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -141,6 +141,9 @@
 
     private:
 
+       status_t unloadSoundModel_l(sound_model_handle_t handle);
+
+
         Mutex                                  mLock;
         wp<SoundTriggerHwService>              mService;
         struct sound_trigger_hw_device*        mHwDevice;
diff --git a/soundtrigger/ISoundTrigger.cpp b/soundtrigger/ISoundTrigger.cpp
index 42280d1..eecc1ea 100644
--- a/soundtrigger/ISoundTrigger.cpp
+++ b/soundtrigger/ISoundTrigger.cpp
@@ -58,7 +58,7 @@
         }
         Parcel data, reply;
         data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
-        data.writeStrongBinder(modelMemory->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(modelMemory));
         status_t status = remote()->transact(LOAD_SOUND_MODEL, data, &reply);
         if (status != NO_ERROR ||
                 (status = (status_t)reply.readInt32()) != NO_ERROR) {
@@ -91,7 +91,7 @@
         } else {
             data.writeInt32(dataMemory->size());
         }
-        data.writeStrongBinder(dataMemory->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(dataMemory));
         status_t status = remote()->transact(START_RECOGNITION, data, &reply);
         if (status != NO_ERROR) {
             status = (status_t)reply.readInt32();
diff --git a/soundtrigger/ISoundTriggerClient.cpp b/soundtrigger/ISoundTriggerClient.cpp
index b0b4428..e0d3add 100644
--- a/soundtrigger/ISoundTriggerClient.cpp
+++ b/soundtrigger/ISoundTriggerClient.cpp
@@ -44,7 +44,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
-        data.writeStrongBinder(eventMemory->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(eventMemory));
         remote()->transact(ON_RECOGNITION_EVENT,
                            data,
                            &reply);
@@ -54,7 +54,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
-        data.writeStrongBinder(eventMemory->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(eventMemory));
         remote()->transact(ON_SOUNDMODEL_EVENT,
                            data,
                            &reply);
@@ -63,7 +63,7 @@
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
-        data.writeStrongBinder(eventMemory->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(eventMemory));
         remote()->transact(ON_SERVICE_STATE_CHANGE,
                            data,
                            &reply);
diff --git a/soundtrigger/ISoundTriggerHwService.cpp b/soundtrigger/ISoundTriggerHwService.cpp
index 05728e9..75f68b8 100644
--- a/soundtrigger/ISoundTriggerHwService.cpp
+++ b/soundtrigger/ISoundTriggerHwService.cpp
@@ -82,7 +82,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
         data.write(&handle, sizeof(sound_trigger_module_handle_t));
-        data.writeStrongBinder(client->asBinder());
+        data.writeStrongBinder(IInterface::asBinder(client));
         remote()->transact(ATTACH, data, &reply);
         status_t status = reply.readInt32();
         if (reply.readInt32() != 0) {
@@ -147,7 +147,7 @@
             reply->writeInt32(status);
             if (module != 0) {
                 reply->writeInt32(1);
-                reply->writeStrongBinder(module->asBinder());
+                reply->writeStrongBinder(IInterface::asBinder(module));
             } else {
                 reply->writeInt32(0);
             }
diff --git a/soundtrigger/SoundTrigger.cpp b/soundtrigger/SoundTrigger.cpp
index 0015c30..2138cb7 100644
--- a/soundtrigger/SoundTrigger.cpp
+++ b/soundtrigger/SoundTrigger.cpp
@@ -104,7 +104,7 @@
     status_t status = service->attach(module, soundTrigger, soundTrigger->mISoundTrigger);
 
     if (status == NO_ERROR && soundTrigger->mISoundTrigger != 0) {
-        soundTrigger->mISoundTrigger->asBinder()->linkToDeath(soundTrigger);
+        IInterface::asBinder(soundTrigger->mISoundTrigger)->linkToDeath(soundTrigger);
     } else {
         ALOGW("Error %d connecting to sound trigger service", status);
         soundTrigger.clear();
@@ -144,7 +144,7 @@
     mCallback.clear();
     if (mISoundTrigger != 0) {
         mISoundTrigger->detach();
-        mISoundTrigger->asBinder()->unlinkToDeath(this);
+        IInterface::asBinder(mISoundTrigger)->unlinkToDeath(this);
         mISoundTrigger = 0;
     }
 }
diff --git a/tools/resampler_tools/Android.mk b/tools/resampler_tools/Android.mk
index e8cbe39..b58e4cd 100644
--- a/tools/resampler_tools/Android.mk
+++ b/tools/resampler_tools/Android.mk
@@ -1,6 +1,6 @@
 # Copyright 2005 The Android Open Source Project
 #
-# Android.mk for resampler_tools 
+# Android.mk for resampler_tools
 #
 
 
diff --git a/tools/resampler_tools/fir.cpp b/tools/resampler_tools/fir.cpp
index 62eddca..fe4d212 100644
--- a/tools/resampler_tools/fir.cpp
+++ b/tools/resampler_tools/fir.cpp
@@ -66,19 +66,20 @@
 
 static void usage(char* name) {
     fprintf(stderr,
-            "usage: %s [-h] [-d] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]"
+            "usage: %s [-h] [-d] [-D] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]"
             " [-f {float|fixed|fixed16}] [-b beta] [-v dBFS] [-l lerp]\n"
-            "       %s [-h] [-d] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]"
+            "       %s [-h] [-d] [-D] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]"
             " [-f {float|fixed|fixed16}] [-b beta] [-v dBFS] -p M/N\n"
             "    -h    this help message\n"
             "    -d    debug, print comma-separated coefficient table\n"
+            "    -D    generate extra declarations\n"
             "    -p    generate poly-phase filter coefficients, with sample increment M/N\n"
             "    -s    sample rate (48000)\n"
             "    -c    cut-off frequency (20478)\n"
             "    -n    number of zero-crossings on one side (8)\n"
             "    -l    number of lerping bits (4)\n"
             "    -m    number of polyphases (related to -l, default 16)\n"
-            "    -f    output format, can be fixed-point or floating-point (fixed)\n"
+            "    -f    output format, can be fixed, fixed16, or float (fixed)\n"
             "    -b    kaiser window parameter beta (7.865 [-80dB])\n"
             "    -v    attenuation in dBFS (0)\n",
             name, name
@@ -97,7 +98,8 @@
     double Fs = 48000;
     double Fc = 20478;
     double atten = 1;
-    int format = 0;
+    int format = 0;     // 0=fixed, 1=float
+    bool declarations = false;
 
     // in order to keep the errors associated with the linear
     // interpolation of the coefficients below the quantization error
@@ -158,11 +160,14 @@
 
     int M = 1 << 4; // number of phases for interpolation
     int ch;
-    while ((ch = getopt(argc, argv, ":hds:c:n:f:l:m:b:p:v:z:")) != -1) {
+    while ((ch = getopt(argc, argv, ":hds:c:n:f:l:m:b:p:v:z:D")) != -1) {
         switch (ch) {
             case 'd':
                 debug = true;
                 break;
+            case 'D':
+                declarations = true;
+                break;
             case 'p':
                 if (sscanf(optarg, "%u/%u", &polyM, &polyN) != 2) {
                     usage(argv[0]);
@@ -225,24 +230,26 @@
     for (int i = M-1 ; i; i>>=1, nz++);
     // generate the right half of the filter
     if (!debug) {
-        printf("// cmd-line: ");
-        for (int i=1 ; i<argc ; i++) {
-            printf("%s ", argv[i]);
+        printf("// cmd-line:");
+        for (int i=0 ; i<argc ; i++) {
+            printf(" %s", argv[i]);
         }
         printf("\n");
-        if (!polyphase) {
-            printf("const int32_t RESAMPLE_FIR_SIZE           = %d;\n", N);
-            printf("const int32_t RESAMPLE_FIR_INT_PHASES     = %d;\n", M);
-            printf("const int32_t RESAMPLE_FIR_NUM_COEF       = %d;\n", nzc);
-        } else {
-            printf("const int32_t RESAMPLE_FIR_SIZE           = %d;\n", 2*nzc*polyN);
-            printf("const int32_t RESAMPLE_FIR_NUM_COEF       = %d;\n", 2*nzc);
+        if (declarations) {
+            if (!polyphase) {
+                printf("const int32_t RESAMPLE_FIR_SIZE           = %d;\n", N);
+                printf("const int32_t RESAMPLE_FIR_INT_PHASES     = %d;\n", M);
+                printf("const int32_t RESAMPLE_FIR_NUM_COEF       = %d;\n", nzc);
+            } else {
+                printf("const int32_t RESAMPLE_FIR_SIZE           = %d;\n", 2*nzc*polyN);
+                printf("const int32_t RESAMPLE_FIR_NUM_COEF       = %d;\n", 2*nzc);
+            }
+            if (!format) {
+                printf("const int32_t RESAMPLE_FIR_COEF_BITS      = %d;\n", nc);
+            }
+            printf("\n");
+            printf("static %s resampleFIR[] = {", !format ? "int32_t" : "float");
         }
-        if (!format) {
-            printf("const int32_t RESAMPLE_FIR_COEF_BITS      = %d;\n", nc);
-        }
-        printf("\n");
-        printf("static %s resampleFIR[] = {", !format ? "int32_t" : "float");
     }
 
     if (!polyphase) {
@@ -260,12 +267,15 @@
                 if (!format) {
                     int64_t yi = toint(y, 1ULL<<(nc-1));
                     if (nc > 16) {
-                        printf("0x%08x, ", int32_t(yi));
+                        printf("0x%08x,", int32_t(yi));
                     } else {
-                        printf("0x%04x, ", int32_t(yi)&0xffff);
+                        printf("0x%04x,", int32_t(yi)&0xffff);
                     }
                 } else {
-                    printf("%.9g%s ", y, debug ? "," : "f,");
+                    printf("%.9g%s", y, debug ? "," : "f,");
+                }
+                if (j != nzc-1) {
+                    printf(" ");
                 }
             }
         }
@@ -283,23 +293,22 @@
                 if (!format) {
                     int64_t yi = toint(y, 1ULL<<(nc-1));
                     if (nc > 16) {
-                        printf("0x%08x, ", int32_t(yi));
+                        printf("0x%08x,", int32_t(yi));
                     } else {
-                        printf("0x%04x, ", int32_t(yi)&0xffff);
+                        printf("0x%04x,", int32_t(yi)&0xffff);
                     }
                 } else {
-                    printf("%.9g%s", y, debug ? "" : "f");
+                    printf("%.9g%s", y, debug ? "," : "f,");
                 }
 
-                if (debug && (i==nzc-1)) {
-                } else {
-                    printf(", ");
+                if (i != nzc-1) {
+                    printf(" ");
                 }
             }
         }
     }
 
-    if (!debug) {
+    if (!debug && declarations) {
         printf("\n};");
     }
     printf("\n");