Merge commit '79edadcea74151b573d5b973d5a421baee693ec1' from
oc-mr1-dev-plus-aosp into stage-aosp-master

Change-Id: I04234f284e3117e8343e7c888646400c81f5a131
Merged-In: Icf228c701afe37dd3c7f00ea9e6fb740b0d450f1
diff --git a/Android.bp b/Android.bp
index a3679b1..e4f12c8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2,5 +2,6 @@
     "camera",
     "drm/*",
     "media/*",
+    "services/*",
     "soundtrigger",
 ]
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index af977b8..907802c 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -59,7 +59,8 @@
         mWrapper(wrapper),
         mInError(false),
         mError(ACAMERA_OK),
-        mIdle(true) {
+        mIdle(true),
+        mCurrentSession(nullptr) {
     mClosing = false;
     // Setup looper thread to perfrom device callbacks to app
     mCbLooper = new ALooper;
@@ -98,18 +99,30 @@
 
 // Device close implementaiton
 CameraDevice::~CameraDevice() {
-    Mutex::Autolock _l(mDeviceLock);
-    if (!isClosed()) {
-        disconnectLocked();
-    }
-    if (mCbLooper != nullptr) {
-        mCbLooper->unregisterHandler(mHandler->id());
-        mCbLooper->stop();
+    sp<ACameraCaptureSession> session = mCurrentSession.promote();
+    {
+        Mutex::Autolock _l(mDeviceLock);
+        if (!isClosed()) {
+            disconnectLocked(session);
+        }
+        mCurrentSession = nullptr;
+        if (mCbLooper != nullptr) {
+            mCbLooper->unregisterHandler(mHandler->id());
+            mCbLooper->stop();
+        }
     }
     mCbLooper.clear();
     mHandler.clear();
 }
 
+void
+CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
+    msg->post();
+    msg.clear();
+    sp<AMessage> cleanupMsg = new AMessage(kWhatCleanUpSessions, mHandler);
+    cleanupMsg->post();
+}
+
 // TODO: cached created request?
 camera_status_t
 CameraDevice::createCaptureRequest(
@@ -146,14 +159,15 @@
         const ACaptureSessionOutputContainer*       outputs,
         const ACameraCaptureSession_stateCallbacks* callbacks,
         /*out*/ACameraCaptureSession** session) {
+    sp<ACameraCaptureSession> currentSession = mCurrentSession.promote();
     Mutex::Autolock _l(mDeviceLock);
     camera_status_t ret = checkCameraClosedOrErrorLocked();
     if (ret != ACAMERA_OK) {
         return ret;
     }
 
-    if (mCurrentSession != nullptr) {
-        mCurrentSession->closeByDevice();
+    if (currentSession != nullptr) {
+        currentSession->closeByDevice();
         stopRepeatingLocked();
     }
 
@@ -264,7 +278,7 @@
         msg->setPointer(kContextKey, session->mUserSessionCallback.context);
         msg->setObject(kSessionSpKey, session);
         msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
-        msg->post();
+        postSessionMsgAndCleanup(msg);
     }
     mIdle = false;
     mBusySession = session;
@@ -328,7 +342,7 @@
         return;
     }
 
-    if (session != mCurrentSession) {
+    if (mCurrentSession != session) {
         // Session has been replaced by other seesion or device is closed
         return;
     }
@@ -349,7 +363,7 @@
 }
 
 void
-CameraDevice::disconnectLocked() {
+CameraDevice::disconnectLocked(sp<ACameraCaptureSession>& session) {
     if (mClosing.exchange(true)) {
         // Already closing, just return
         ALOGW("Camera device %s is already closing.", getId());
@@ -361,9 +375,8 @@
     }
     mRemote = nullptr;
 
-    if (mCurrentSession != nullptr) {
-        mCurrentSession->closeByDevice();
-        mCurrentSession = nullptr;
+    if (session != nullptr) {
+        session->closeByDevice();
     }
 }
 
@@ -404,7 +417,7 @@
     // This should never happen because creating a new session will close
     // previous one and thus reject any API call from previous session.
     // But still good to check here in case something unexpected happen.
-    if (session != mCurrentSession) {
+    if (mCurrentSession != session) {
         ALOGE("Camera %s session %p is not current active session!", getId(), session);
         return ACAMERA_ERROR_INVALID_OPERATION;
     }
@@ -415,12 +428,13 @@
     }
 
     mFlushing = true;
+
     // Send onActive callback to guarantee there is always active->ready transition
     sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
     msg->setPointer(kContextKey, session->mUserSessionCallback.context);
     msg->setObject(kSessionSpKey, session);
     msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
-    msg->post();
+    postSessionMsgAndCleanup(msg);
 
     // If device is already idling, send callback and exit early
     if (mIdle) {
@@ -428,7 +442,7 @@
         msg->setPointer(kContextKey, session->mUserSessionCallback.context);
         msg->setObject(kSessionSpKey, session);
         msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onReady);
-        msg->post();
+        postSessionMsgAndCleanup(msg);
         mFlushing = false;
         return ACAMERA_OK;
     }
@@ -568,7 +582,7 @@
         msg->setObject(kSessionSpKey, mBusySession);
         msg->setPointer(kCallbackFpKey, (void*) mBusySession->mUserSessionCallback.onReady);
         mBusySession.clear();
-        msg->post();
+        postSessionMsgAndCleanup(msg);
     }
     mIdle = true;
 
@@ -728,7 +742,7 @@
         msg->setObject(kCaptureRequestKey, request);
         msg->setPointer(kAnwKey, (void*) anw);
         msg->setInt64(kFrameNumberKey, frameNumber);
-        msg->post();
+        postSessionMsgAndCleanup(msg);
     } else { // Handle other capture failures
         // Fire capture failure callback if there is one registered
         ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
@@ -746,7 +760,7 @@
         msg->setPointer(kCallbackFpKey, (void*) onError);
         msg->setObject(kCaptureRequestKey, request);
         msg->setObject(kCaptureFailureKey, failure);
-        msg->post();
+        postSessionMsgAndCleanup(msg);
 
         // Update tracker
         mFrameNumberTracker.updateTracker(frameNumber, /*isError*/true);
@@ -769,6 +783,9 @@
         case kWhatCaptureBufferLost:
             ALOGV("%s: Received msg %d", __FUNCTION__, msg->what());
             break;
+        case kWhatCleanUpSessions:
+            mCachedSessions.clear();
+            return;
         default:
             ALOGE("%s:Error: unknown device callback %d", __FUNCTION__, msg->what());
             return;
@@ -842,6 +859,7 @@
                 return;
             }
             sp<ACameraCaptureSession> session(static_cast<ACameraCaptureSession*>(obj.get()));
+            mCachedSessions.push(session);
             sp<CaptureRequest> requestSp = nullptr;
             switch (msg->what()) {
                 case kWhatCaptureStart:
@@ -1053,7 +1071,7 @@
         msg->setObject(kSessionSpKey, cbh.mSession);
         msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted);
         msg->setInt32(kSequenceIdKey, sequenceId);
-        msg->post();
+        postSessionMsgAndCleanup(msg);
     } else {
         // Use mSequenceLastFrameNumberMap to track
         mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
@@ -1110,7 +1128,7 @@
             // before cbh goes out of scope and causing we call the session
             // destructor while holding device lock
             cbh.mSession.clear();
-            msg->post();
+            postSessionMsgAndCleanup(msg);
         }
 
         // No need to track sequence complete if there is no callback registered
@@ -1137,6 +1155,7 @@
         return ret; // device has been closed
     }
 
+    sp<ACameraCaptureSession> session = dev->mCurrentSession.promote();
     Mutex::Autolock _l(dev->mDeviceLock);
     if (dev->mRemote == nullptr) {
         return ret; // device has been closed
@@ -1145,10 +1164,10 @@
         case ERROR_CAMERA_DISCONNECTED:
         {
             // Camera is disconnected, close the session and expect no more callbacks
-            if (dev->mCurrentSession != nullptr) {
-                dev->mCurrentSession->closeByDevice();
-                dev->mCurrentSession = nullptr;
+            if (session != nullptr) {
+                session->closeByDevice();
             }
+            dev->mCurrentSession = nullptr;
             sp<AMessage> msg = new AMessage(kWhatOnDisconnected, dev->mHandler);
             msg->setPointer(kContextKey, dev->mAppCallbacks.context);
             msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
@@ -1216,6 +1235,7 @@
             dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
             return ret;
         }
+
         sp<AMessage> msg = new AMessage(kWhatSessionStateCb, dev->mHandler);
         msg->setPointer(kContextKey, dev->mBusySession->mUserSessionCallback.context);
         msg->setObject(kSessionSpKey, dev->mBusySession);
@@ -1223,7 +1243,7 @@
         // Make sure we clear the sp first so the session destructor can
         // only happen on handler thread (where we don't hold device/session lock)
         dev->mBusySession.clear();
-        msg->post();
+        dev->postSessionMsgAndCleanup(msg);
     }
     dev->mIdle = true;
     dev->mFlushing = false;
@@ -1265,7 +1285,7 @@
         msg->setPointer(kCallbackFpKey, (void*) onStart);
         msg->setObject(kCaptureRequestKey, request);
         msg->setInt64(kTimeStampKey, timestamp);
-        msg->post();
+        dev->postSessionMsgAndCleanup(msg);
     }
     return ret;
 }
@@ -1328,7 +1348,7 @@
         msg->setPointer(kCallbackFpKey, (void*) onResult);
         msg->setObject(kCaptureRequestKey, request);
         msg->setObject(kCaptureResultKey, result);
-        msg->post();
+        dev->postSessionMsgAndCleanup(msg);
     }
 
     if (!isPartialResult) {
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 78a7891..6ed3881 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -96,7 +96,7 @@
     // device goes into fatal error state after this
     void setCameraDeviceErrorLocked(camera_status_t error);
 
-    void disconnectLocked(); // disconnect from camera service
+    void disconnectLocked(sp<ACameraCaptureSession>& session); // disconnect from camera service
 
     camera_status_t stopRepeatingLocked();
 
@@ -138,6 +138,9 @@
 
     camera_status_t configureStreamsLocked(const ACaptureSessionOutputContainer* outputs);
 
+    // Input message will be posted and cleared after this returns
+    void postSessionMsgAndCleanup(sp<AMessage>& msg);
+
     static camera_status_t getIGBPfromAnw(
             ANativeWindow* anw, sp<IGraphicBufferProducer>& out);
 
@@ -185,7 +188,9 @@
         kWhatCaptureFail,      // onCaptureFailed
         kWhatCaptureSeqEnd,    // onCaptureSequenceCompleted
         kWhatCaptureSeqAbort,  // onCaptureSequenceAborted
-        kWhatCaptureBufferLost // onCaptureBufferLost
+        kWhatCaptureBufferLost,// onCaptureBufferLost
+        // Internal cleanup
+        kWhatCleanUpSessions   // Cleanup cached sp<ACameraCaptureSession>
     };
     static const char* kContextKey;
     static const char* kDeviceKey;
@@ -199,10 +204,16 @@
     static const char* kSequenceIdKey;
     static const char* kFrameNumberKey;
     static const char* kAnwKey;
+
     class CallbackHandler : public AHandler {
       public:
-        CallbackHandler() {}
         void onMessageReceived(const sp<AMessage> &msg) override;
+
+      private:
+        // This handler will cache all capture session sp until kWhatCleanUpSessions
+        // is processed. This is used to guarantee the last session reference is always
+        // being removed in callback thread without holding camera device lock
+        Vector<sp<ACameraCaptureSession>> mCachedSessions;
     };
     sp<CallbackHandler> mHandler;
 
@@ -210,7 +221,7 @@
      * Capture session related members *
      ***********************************/
     // The current active session
-    ACameraCaptureSession* mCurrentSession = nullptr;
+    wp<ACameraCaptureSession> mCurrentSession;
     bool mFlushing = false;
 
     int mNextSessionId = 0;
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index 9b7f6f4..6c9e85a 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -90,18 +90,18 @@
 };
 
 /**
- * Camera device state callbacks to be used in {@link ACameraDevice_stateCallbacks}.
+ * Camera device state callbacks to be used in {@link ACameraDevice_StateCallbacks}.
  *
- * @param context The optional context in {@link ACameraDevice_stateCallbacks} will be
+ * @param context The optional context in {@link ACameraDevice_StateCallbacks} will be
  *                passed to this callback.
  * @param device The {@link ACameraDevice} that is being disconnected.
  */
 typedef void (*ACameraDevice_StateCallback)(void* context, ACameraDevice* device);
 
 /**
- * Camera device error state callbacks to be used in {@link ACameraDevice_stateCallbacks}.
+ * Camera device error state callbacks to be used in {@link ACameraDevice_StateCallbacks}.
  *
- * @param context The optional context in {@link ACameraDevice_stateCallbacks} will be
+ * @param context The optional context in {@link ACameraDevice_StateCallbacks} will be
  *                passed to this callback.
  * @param device The {@link ACameraDevice} that is being disconnected.
  * @param error The error code describes the cause of this error callback. See the folowing
@@ -150,7 +150,7 @@
      *
      */
     ACameraDevice_ErrorStateCallback  onError;
-} ACameraDevice_stateCallbacks;
+} ACameraDevice_StateCallbacks;
 
 /**
  * Close the connection and free this ACameraDevice synchronously. Access to the ACameraDevice
diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h
index 5b5c98b..e5b3ad8 100644
--- a/camera/ndk/include/camera/NdkCameraManager.h
+++ b/camera/ndk/include/camera/NdkCameraManager.h
@@ -232,18 +232,18 @@
  * priority when accessing the camera, and this method will succeed even if the camera device is
  * in use by another camera API client. Any lower-priority application that loses control of the
  * camera in this way will receive an
- * {@link ACameraDevice_stateCallbacks#onDisconnected} callback.</p>
+ * {@link ACameraDevice_StateCallbacks#onDisconnected} callback.</p>
  *
  * <p>Once the camera is successfully opened,the ACameraDevice can then be set up
  * for operation by calling {@link ACameraDevice_createCaptureSession} and
  * {@link ACameraDevice_createCaptureRequest}.</p>
  *
  * <p>If the camera becomes disconnected after this function call returns,
- * {@link ACameraDevice_stateCallbacks#onDisconnected} with a
+ * {@link ACameraDevice_StateCallbacks#onDisconnected} with a
  * ACameraDevice in the disconnected state will be called.</p>
  *
  * <p>If the camera runs into error after this function call returns,
- * {@link ACameraDevice_stateCallbacks#onError} with a
+ * {@link ACameraDevice_StateCallbacks#onError} with a
  * ACameraDevice in the error state will be called.</p>
  *
  * @param manager the {@link ACameraManager} of interest.
diff --git a/drm/common/Android.bp b/drm/common/Android.bp
index 0098c89..1552c3f 100644
--- a/drm/common/Android.bp
+++ b/drm/common/Android.bp
@@ -33,6 +33,8 @@
         "ReadWriteUtils.cpp",
     ],
 
+    cflags: ["-Wall", "-Werror"],
+
     static_libs: ["libbinder"],
 
     export_include_dirs: ["include"],
diff --git a/drm/libdrmframework/plugins/common/util/Android.bp b/drm/libdrmframework/plugins/common/util/Android.bp
index 0c0b6f2..7372eb7 100644
--- a/drm/libdrmframework/plugins/common/util/Android.bp
+++ b/drm/libdrmframework/plugins/common/util/Android.bp
@@ -19,5 +19,7 @@
 
     srcs: ["src/MimeTypeUtil.cpp"],
 
+    cflags: ["-Wall", "-Werror"],
+
     export_include_dirs: ["include"],
 }
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index 3f0f5f7..28a78aa 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -21,6 +21,9 @@
         "-DUSE_64BIT_DRM_API",
         // The flag below turns on local debug printouts
         //"-DDRM_OMA_FL_ENGINE_DEBUG",
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-variable",
     ],
 
     srcs: ["src/FwdLockEngine.cpp"],
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.bp b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.bp
index 698f278..3be327a 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.bp
@@ -19,6 +19,8 @@
 
     srcs: ["FwdLockGlue.c"],
 
+    cflags: ["-Wall", "-Werror"],
+
     shared_libs: ["libcrypto"],
 
     export_include_dirs: ["."],
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.bp b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.bp
index 33f2fe0..d4e04b8 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.bp
@@ -19,6 +19,8 @@
 
     srcs: ["FwdLockConv.c"],
 
+    cflags: ["-Wall", "-Werror"],
+
     shared_libs: ["libcrypto"],
     static_libs: ["libfwdlock-common"],
 
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.bp b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.bp
index b6d7a06..0bf2737 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.bp
@@ -19,6 +19,8 @@
 
     srcs: ["FwdLockFile.c"],
 
+    cflags: ["-Wall", "-Werror"],
+
     shared_libs: ["libcrypto"],
     static_libs: ["libfwdlock-common"],
 
diff --git a/drm/libdrmframework/plugins/passthru/Android.bp b/drm/libdrmframework/plugins/passthru/Android.bp
index 1dcf89c..05b6440 100644
--- a/drm/libdrmframework/plugins/passthru/Android.bp
+++ b/drm/libdrmframework/plugins/passthru/Android.bp
@@ -32,5 +32,7 @@
     cflags: [
         // Set the following flag to enable the decryption passthru flow
         //"-DENABLE_PASSTHRU_DECRYPTION",
+        "-Wall",
+        "-Werror",
     ],
 }
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index f906564..0c14201 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -34,8 +34,8 @@
         "libstagefright_foundation",
         "libutils",
         "android.hardware.drm@1.0",
+        "libhidlallocatorutils",
         "libhidlbase",
-        "libhidlmemory",
         "libhidltransport",
     ],
 
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index d613a5b..b9b3685 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -29,6 +29,7 @@
 #include <media/stagefright/foundation/AString.h>
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/MediaErrors.h>
+#include <hidlmemory/FrameworkUtils.h>
 
 using ::android::hardware::drm::V1_0::BufferType;
 using ::android::hardware::drm::V1_0::DestinationBuffer;
@@ -227,6 +228,9 @@
  * are sent by providing an offset into the heap and a buffer size.
  */
 int32_t CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
+    using ::android::hardware::fromHeap;
+    using ::android::hardware::HidlMemory;
+
     if (heap == NULL) {
         ALOGE("setHeapBase(): heap is NULL");
         return -1;
@@ -240,12 +244,9 @@
     Mutex::Autolock autoLock(mLock);
 
     int32_t seqNum = mHeapSeqNum++;
-    int fd = heap->getHeapID();
-    nativeHandle->data[0] = fd;
-    auto hidlHandle = hidl_handle(nativeHandle);
-    auto hidlMemory = hidl_memory("ashmem", hidlHandle, heap->getSize());
+    sp<HidlMemory> hidlMemory = fromHeap(heap);
     mHeapBases.add(seqNum, mNextBufferId);
-    Return<void> hResult = mPlugin->setSharedBufferBase(hidlMemory, mNextBufferId++);
+    Return<void> hResult = mPlugin->setSharedBufferBase(*hidlMemory, mNextBufferId++);
     ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
     return seqNum;
 }
diff --git a/drm/mediadrm/plugins/clearkey/Android.bp b/drm/mediadrm/plugins/clearkey/Android.bp
index 2973fcf..385815c 100644
--- a/drm/mediadrm/plugins/clearkey/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/Android.bp
@@ -35,6 +35,8 @@
     vendor: true,
     relative_install_path: "mediadrm",
 
+    cflags: ["-Wall", "-Werror"],
+
     shared_libs: [
         "libcrypto",
         "liblog",
diff --git a/drm/mediadrm/plugins/clearkey/tests/Android.bp b/drm/mediadrm/plugins/clearkey/tests/Android.bp
index 0fcfc64..ea17bbb 100644
--- a/drm/mediadrm/plugins/clearkey/tests/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/tests/Android.bp
@@ -21,6 +21,8 @@
     name: "ClearKeyDrmUnitTest",
     vendor: true,
 
+    cflags: ["-Wall", "-Werror"],
+
     srcs: [
         "AesCtrDecryptorUnittest.cpp",
         "InitDataParserUnittest.cpp",
diff --git a/drm/mediadrm/plugins/mock/Android.bp b/drm/mediadrm/plugins/mock/Android.bp
index abd1884..dd2ad7b 100644
--- a/drm/mediadrm/plugins/mock/Android.bp
+++ b/drm/mediadrm/plugins/mock/Android.bp
@@ -32,5 +32,7 @@
     cflags: [
         // Set the following flag to enable the decryption passthru flow
         //"-DENABLE_PASSTHRU_DECRYPTION",
+        "-Wall",
+        "-Werror",
     ],
 }
diff --git a/media/libaaudio/Android.bp b/media/libaaudio/Android.bp
index 6e60f24..f00f7a8 100644
--- a/media/libaaudio/Android.bp
+++ b/media/libaaudio/Android.bp
@@ -28,3 +28,10 @@
     first_version: "26",
     unversioned_until: "current",
 }
+
+cc_library_headers {
+    name: "libaaudio_headers",
+    export_include_dirs: ["include"],
+}
+
+subdirs = ["*"]
diff --git a/media/libaaudio/Android.mk b/media/libaaudio/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/media/libaaudio/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/media/libaaudio/examples/Android.bp b/media/libaaudio/examples/Android.bp
new file mode 100644
index 0000000..f2e00a7
--- /dev/null
+++ b/media/libaaudio/examples/Android.bp
@@ -0,0 +1,4 @@
+cc_library_headers {
+    name: "libaaudio_example_utils",
+    export_include_dirs: ["."],
+}
diff --git a/media/libaaudio/examples/Android.mk b/media/libaaudio/examples/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/media/libaaudio/examples/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/media/libaaudio/examples/input_monitor/Android.mk b/media/libaaudio/examples/input_monitor/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/media/libaaudio/examples/input_monitor/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/media/libaaudio/examples/input_monitor/jni/Android.mk b/media/libaaudio/examples/input_monitor/jni/Android.mk
index 9b1ce2c..a0b981c 100644
--- a/media/libaaudio/examples/input_monitor/jni/Android.mk
+++ b/media/libaaudio/examples/input_monitor/jni/Android.mk
@@ -10,6 +10,7 @@
 
 # NDK recommends using this kind of relative path instead of an absolute path.
 LOCAL_SRC_FILES:= ../src/input_monitor.cpp
+LOCAL_CFLAGS := -Wall -Werror
 LOCAL_SHARED_LIBRARIES := libaaudio
 LOCAL_MODULE := input_monitor
 include $(BUILD_EXECUTABLE)
@@ -22,6 +23,7 @@
     frameworks/av/media/libaaudio/examples/utils
 
 LOCAL_SRC_FILES:= ../src/input_monitor_callback.cpp
+LOCAL_CFLAGS := -Wall -Werror
 LOCAL_SHARED_LIBRARIES := libaaudio
 LOCAL_MODULE := input_monitor_callback
 include $(BUILD_EXECUTABLE)
diff --git a/media/libaaudio/examples/input_monitor/src/input_monitor.cpp b/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
index 9feb118..e5ad2d9 100644
--- a/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
+++ b/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
@@ -40,7 +40,6 @@
     int actualSamplesPerFrame;
     int actualSampleRate;
     aaudio_format_t       actualDataFormat;
-    aaudio_sharing_mode_t actualSharingMode;
 
     AAudioStream *aaudioStream = nullptr;
     aaudio_stream_state_t state;
@@ -54,7 +53,6 @@
     int64_t previousFramePosition = -1;
     int16_t *data = nullptr;
     float peakLevel = 0.0;
-    int loopCounter = 0;
     int32_t deviceId;
 
     // Make printf print immediately so that debug info is not stuck
diff --git a/media/libaaudio/examples/loopback/Android.mk b/media/libaaudio/examples/loopback/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/media/libaaudio/examples/loopback/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/media/libaaudio/examples/loopback/jni/Android.mk b/media/libaaudio/examples/loopback/jni/Android.mk
index d78f286..1fe3def 100644
--- a/media/libaaudio/examples/loopback/jni/Android.mk
+++ b/media/libaaudio/examples/loopback/jni/Android.mk
@@ -9,6 +9,7 @@
 
 # NDK recommends using this kind of relative path instead of an absolute path.
 LOCAL_SRC_FILES:= ../src/loopback.cpp
+LOCAL_CFLAGS := -Wall -Werror
 LOCAL_SHARED_LIBRARIES := libaaudio
 LOCAL_MODULE := aaudio_loopback
 include $(BUILD_EXECUTABLE)
diff --git a/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h b/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
index 21cf341..276b45f 100644
--- a/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
+++ b/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
@@ -432,9 +432,7 @@
             int needleSize = (int) (sizeof(s_Impulse) / sizeof(float));
             float *haystack = audioRecorder.getData();
             int haystackSize = audioRecorder.size();
-            int result = measureLatencyFromEchos(haystack, haystackSize,
-                                                 needle, needleSize,
-                                                 &latencyReport);
+            measureLatencyFromEchos(haystack, haystackSize, needle, needleSize, &latencyReport);
             if (latencyReport.confidence < 0.01) {
                 printf("   ERROR - confidence too low = %f\n", latencyReport.confidence);
             } else {
@@ -580,7 +578,6 @@
 
     int           mDownCounter = 500;
     int           mLoopCounter = 0;
-    int           mLoopStart = 1000;
     float         mPulseThreshold = 0.02f;
     float         mSilenceThreshold = 0.002f;
     float         mMeasuredLoopGain = 0.0f;
@@ -651,7 +648,6 @@
     void process(float *inputData, int inputChannelCount,
                  float *outputData, int outputChannelCount,
                  int numFrames) override {
-        float sample;
         float peak = measurePeakAmplitude(inputData, inputChannelCount, numFrames);
         if (peak > mPeakAmplitude) {
             mPeakAmplitude = peak;
@@ -779,8 +775,6 @@
     int32_t mFrameCounter = 0;
     float   mOutputAmplitude = 0.75;
 
-    int32_t mZeroCrossings = 0;
-
     PseudoRandom  mWhiteNoise;
     float   mNoiseAmplitude = 0.00; // Used to experiment with warbling caused by DRC.
 
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index be833e6..b678d8a 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -257,24 +257,17 @@
     aaudio_result_t      result = AAUDIO_OK;
     aaudio_sharing_mode_t requestedInputSharingMode     = AAUDIO_SHARING_MODE_SHARED;
     int                   requestedInputChannelCount = NUM_INPUT_CHANNELS;
-    const int             requestedOutputChannelCount = AAUDIO_UNSPECIFIED;
-    int                   actualSampleRate = 0;
     const aaudio_format_t requestedInputFormat = AAUDIO_FORMAT_PCM_I16;
     const aaudio_format_t requestedOutputFormat = AAUDIO_FORMAT_PCM_FLOAT;
     aaudio_format_t       actualInputFormat;
     aaudio_format_t       actualOutputFormat;
-    aaudio_performance_mode_t outputPerformanceLevel = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
     aaudio_performance_mode_t inputPerformanceLevel = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
 
     int testMode = TEST_ECHO_LATENCY;
     double gain = 1.0;
 
-    aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
     int32_t framesPerBurst = 0;
     float *outputData = NULL;
-    double deviation;
-    double latency;
-    int32_t burstsPerBuffer = 1; // single buffered
 
     // Make printf print immediately so that debug info is not stuck
     // in a buffer if we hang or crash.
diff --git a/media/libaaudio/examples/utils/AAudioExampleUtils.h b/media/libaaudio/examples/utils/AAudioExampleUtils.h
index d817664..f608589 100644
--- a/media/libaaudio/examples/utils/AAudioExampleUtils.h
+++ b/media/libaaudio/examples/utils/AAudioExampleUtils.h
@@ -86,7 +86,8 @@
     time->tv_nsec = nanoseconds - (time->tv_sec * NANOS_PER_SECOND);
 }
 
-static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
+template <class T = clockid_t>
+int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
     struct timespec time;
     int result = clock_gettime(clockId, &time);
     if (result < 0) {
@@ -95,7 +96,7 @@
     return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
 }
 
-static void displayPeakLevel(float peakLevel) {
+void displayPeakLevel(float peakLevel) {
     printf("%5.3f ", peakLevel);
     const int maxStars = 50; // arbitrary, fits on one line
     int numStars = (int) (peakLevel * maxStars);
@@ -113,7 +114,7 @@
  * @param sampleRate
  * @return latency in milliseconds
  */
-static double calculateLatencyMillis(int64_t position1, int64_t nanoseconds1,
+double calculateLatencyMillis(int64_t position1, int64_t nanoseconds1,
                               int64_t position2, int64_t nanoseconds2,
                               int64_t sampleRate) {
     int64_t deltaFrames = position2 - position1;
diff --git a/media/libaaudio/examples/write_sine/Android.mk b/media/libaaudio/examples/write_sine/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/media/libaaudio/examples/write_sine/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/media/libaaudio/examples/write_sine/jni/Android.mk b/media/libaaudio/examples/write_sine/jni/Android.mk
index d630e76..1a1bd43 100644
--- a/media/libaaudio/examples/write_sine/jni/Android.mk
+++ b/media/libaaudio/examples/write_sine/jni/Android.mk
@@ -10,6 +10,7 @@
 
 # NDK recommends using this kind of relative path instead of an absolute path.
 LOCAL_SRC_FILES:= ../src/write_sine.cpp
+LOCAL_CFLAGS := -Wall -Werror
 LOCAL_SHARED_LIBRARIES := libaaudio
 LOCAL_MODULE := write_sine
 include $(BUILD_EXECUTABLE)
@@ -22,6 +23,7 @@
     frameworks/av/media/libaaudio/examples/utils
 
 LOCAL_SRC_FILES:= ../src/write_sine_callback.cpp
+LOCAL_CFLAGS := -Wall -Werror
 LOCAL_SHARED_LIBRARIES := libaaudio
 LOCAL_MODULE := write_sine_callback
 include $(BUILD_EXECUTABLE)
diff --git a/media/libaaudio/examples/write_sine/src/write_sine.cpp b/media/libaaudio/examples/write_sine/src/write_sine.cpp
index 677fb6c..8c6f783 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine.cpp
@@ -44,7 +44,6 @@
     AAudioStream *aaudioStream = nullptr;
     int32_t  framesPerBurst = 0;
     int32_t  framesPerWrite = 0;
-    int32_t  bufferCapacity = 0;
     int32_t  framesToPlay = 0;
     int32_t  framesLeft = 0;
     int32_t  xRunCount = 0;
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
new file mode 100644
index 0000000..788833b
--- /dev/null
+++ b/media/libaaudio/src/Android.bp
@@ -0,0 +1,66 @@
+cc_library {
+    name: "libaaudio",
+
+    local_include_dirs: [
+        "binding",
+        "client",
+        "core",
+        "fifo",
+        "legacy",
+        "utility",
+    ],
+    export_include_dirs: ["."],
+    header_libs: ["libaaudio_headers"],
+    export_header_lib_headers: ["libaaudio_headers"],
+
+    srcs: [
+        "core/AudioStream.cpp",
+        "core/AudioStreamBuilder.cpp",
+        "core/AAudioAudio.cpp",
+        "core/AAudioStreamParameters.cpp",
+        "legacy/AudioStreamLegacy.cpp",
+        "legacy/AudioStreamRecord.cpp",
+        "legacy/AudioStreamTrack.cpp",
+        "utility/AAudioUtilities.cpp",
+        "utility/FixedBlockAdapter.cpp",
+        "utility/FixedBlockReader.cpp",
+        "utility/FixedBlockWriter.cpp",
+        "utility/LinearRamp.cpp",
+        "fifo/FifoBuffer.cpp",
+        "fifo/FifoControllerBase.cpp",
+        "client/AudioEndpoint.cpp",
+        "client/AudioStreamInternal.cpp",
+        "client/AudioStreamInternalCapture.cpp",
+        "client/AudioStreamInternalPlay.cpp",
+        "client/IsochronousClockModel.cpp",
+        "binding/AudioEndpointParcelable.cpp",
+        "binding/AAudioBinderClient.cpp",
+        "binding/AAudioStreamRequest.cpp",
+        "binding/AAudioStreamConfiguration.cpp",
+        "binding/IAAudioClient.cpp",
+        "binding/IAAudioService.cpp",
+        "binding/RingBufferParcelable.cpp",
+        "binding/SharedMemoryParcelable.cpp",
+        "binding/SharedRegionParcelable.cpp",
+    ],
+
+    cflags: [
+        "-Wno-unused-parameter",
+        "-Wall",
+        "-Werror",
+
+        // By default, all symbols are hidden.
+        // "-fvisibility=hidden",
+        // AAUDIO_API is used to explicitly export a function or a variable as a visible symbol.
+        "-DAAUDIO_API=__attribute__((visibility(\"default\")))",
+    ],
+
+    shared_libs: [
+        "libaudioclient",
+        "liblog",
+        "libcutils",
+        "libutils",
+        "libbinder",
+        "libaudiomanager",
+    ],
+}
diff --git a/media/libaaudio/src/Android.mk b/media/libaaudio/src/Android.mk
deleted file mode 100644
index 6861248..0000000
--- a/media/libaaudio/src/Android.mk
+++ /dev/null
@@ -1,128 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-# ======================= STATIC LIBRARY ==========================
-# This is being built because it make AAudio testing very easy with a complete executable.
-# TODO Remove this target later, when not needed.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libaaudio
-LOCAL_MODULE_TAGS := optional
-
-LIBAAUDIO_DIR := $(TOP)/frameworks/av/media/libaaudio
-LIBAAUDIO_SRC_DIR := $(LIBAAUDIO_DIR)/src
-
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-    frameworks/native/include \
-    system/core/base/include \
-    frameworks/native/media/libaaudio/include/include \
-    frameworks/av/media/libaaudio/include \
-    frameworks/native/include \
-    frameworks/av/media/libaudioclient/include \
-    $(LOCAL_PATH) \
-    $(LOCAL_PATH)/binding \
-    $(LOCAL_PATH)/client \
-    $(LOCAL_PATH)/core \
-    $(LOCAL_PATH)/fifo \
-    $(LOCAL_PATH)/legacy \
-    $(LOCAL_PATH)/utility
-
-# If you add a file here then also add it below in the SHARED target
-LOCAL_SRC_FILES = \
-    core/AudioStream.cpp \
-    core/AudioStreamBuilder.cpp \
-    core/AAudioAudio.cpp \
-    core/AAudioStreamParameters.cpp \
-    legacy/AudioStreamLegacy.cpp \
-    legacy/AudioStreamRecord.cpp \
-    legacy/AudioStreamTrack.cpp \
-    utility/AAudioUtilities.cpp \
-    utility/FixedBlockAdapter.cpp \
-    utility/FixedBlockReader.cpp \
-    utility/FixedBlockWriter.cpp \
-    utility/LinearRamp.cpp \
-    fifo/FifoBuffer.cpp \
-    fifo/FifoControllerBase.cpp \
-    client/AudioEndpoint.cpp \
-    client/AudioStreamInternal.cpp \
-    client/AudioStreamInternalCapture.cpp \
-    client/AudioStreamInternalPlay.cpp \
-    client/IsochronousClockModel.cpp \
-    binding/AudioEndpointParcelable.cpp \
-    binding/AAudioBinderClient.cpp \
-    binding/AAudioStreamRequest.cpp \
-    binding/AAudioStreamConfiguration.cpp \
-    binding/IAAudioClient.cpp \
-    binding/IAAudioService.cpp \
-    binding/RingBufferParcelable.cpp \
-    binding/SharedMemoryParcelable.cpp \
-    binding/SharedRegionParcelable.cpp
-
-LOCAL_CFLAGS += -Wno-unused-parameter -Wall -Werror
-
-# By default, all symbols are hidden.
-# LOCAL_CFLAGS += -fvisibility=hidden
-# AAUDIO_API is used to explicitly export a function or a variable as a visible symbol.
-LOCAL_CFLAGS += -DAAUDIO_API='__attribute__((visibility("default")))'
-
-include $(BUILD_STATIC_LIBRARY)
-
-# ======================= SHARED LIBRARY ==========================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libaaudio
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-    frameworks/native/include \
-    system/core/base/include \
-    frameworks/native/media/libaaudio/include/include \
-    frameworks/av/media/libaaudio/include \
-    $(LOCAL_PATH) \
-    $(LOCAL_PATH)/binding \
-    $(LOCAL_PATH)/client \
-    $(LOCAL_PATH)/core \
-    $(LOCAL_PATH)/fifo \
-    $(LOCAL_PATH)/legacy \
-    $(LOCAL_PATH)/utility
-
-LOCAL_SRC_FILES = core/AudioStream.cpp \
-    core/AudioStreamBuilder.cpp \
-    core/AAudioAudio.cpp \
-    core/AAudioStreamParameters.cpp \
-    legacy/AudioStreamLegacy.cpp \
-    legacy/AudioStreamRecord.cpp \
-    legacy/AudioStreamTrack.cpp \
-    utility/AAudioUtilities.cpp \
-    utility/FixedBlockAdapter.cpp \
-    utility/FixedBlockReader.cpp \
-    utility/FixedBlockWriter.cpp \
-    utility/LinearRamp.cpp \
-    fifo/FifoBuffer.cpp \
-    fifo/FifoControllerBase.cpp \
-    client/AudioEndpoint.cpp \
-    client/AudioStreamInternal.cpp \
-    client/AudioStreamInternalCapture.cpp \
-    client/AudioStreamInternalPlay.cpp \
-    client/IsochronousClockModel.cpp \
-    binding/AudioEndpointParcelable.cpp \
-    binding/AAudioBinderClient.cpp \
-    binding/AAudioStreamRequest.cpp \
-    binding/AAudioStreamConfiguration.cpp \
-    binding/IAAudioClient.cpp \
-    binding/IAAudioService.cpp \
-    binding/RingBufferParcelable.cpp \
-    binding/SharedMemoryParcelable.cpp \
-    binding/SharedRegionParcelable.cpp
-
-LOCAL_CFLAGS += -Wno-unused-parameter -Wall -Werror
-
-# By default, all symbols are hidden.
-# LOCAL_CFLAGS += -fvisibility=hidden
-# AAUDIO_API is used to explicitly export a function or a variable as a visible symbol.
-LOCAL_CFLAGS += -DAAUDIO_API='__attribute__((visibility("default")))'
-
-LOCAL_SHARED_LIBRARIES := libaudioclient liblog libcutils libutils libbinder libaudiomanager
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
new file mode 100644
index 0000000..19c56d3
--- /dev/null
+++ b/media/libaaudio/tests/Android.bp
@@ -0,0 +1,88 @@
+cc_defaults {
+    name: "libaaudio_tests_defaults",
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
+
+cc_test {
+    name: "test_aaudio_marshalling",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_marshalling.cpp"],
+    shared_libs: [
+        "libaaudio",
+        "libbinder",
+        "libcutils",
+        "libutils",
+    ],
+}
+
+cc_test {
+    name: "test_block_adapter",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_block_adapter.cpp"],
+    shared_libs: ["libaaudio"],
+}
+
+cc_test {
+    name: "test_timestamps",
+    srcs: ["test_timestamps.cpp"],
+    header_libs: ["libaaudio_example_utils"],
+    shared_libs: ["libaaudio"],
+}
+
+cc_test {
+    name: "test_linear_ramp",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_linear_ramp.cpp"],
+    shared_libs: ["libaaudio"],
+}
+
+cc_test {
+    name: "test_open_params",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_open_params.cpp"],
+    shared_libs: [
+        "libaaudio",
+        "libbinder",
+        "libcutils",
+        "libutils",
+    ],
+}
+
+cc_test {
+    name: "test_no_close",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_no_close.cpp"],
+    shared_libs: [
+        "libaaudio",
+        "libbinder",
+        "libcutils",
+        "libutils",
+    ],
+}
+
+cc_test {
+    name: "test_aaudio_recovery",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_recovery.cpp"],
+    shared_libs: [
+        "libaaudio",
+        "libbinder",
+        "libcutils",
+        "libutils",
+    ],
+}
+
+cc_test {
+    name: "test_n_streams",
+    defaults: ["libaaudio_tests_defaults"],
+    srcs: ["test_n_streams.cpp"],
+    shared_libs: [
+        "libaaudio",
+        "libbinder",
+        "libcutils",
+        "libutils",
+    ],
+}
diff --git a/media/libaaudio/tests/Android.mk b/media/libaaudio/tests/Android.mk
deleted file mode 100644
index 37b010d..0000000
--- a/media/libaaudio/tests/Android.mk
+++ /dev/null
@@ -1,82 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-    frameworks/av/media/libaaudio/include \
-    frameworks/av/media/libaaudio/src
-LOCAL_SRC_FILES:= test_marshalling.cpp
-LOCAL_SHARED_LIBRARIES := libaaudio libbinder libcutils libutils
-LOCAL_MODULE := test_aaudio_marshalling
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-    frameworks/av/media/libaaudio/include \
-    frameworks/av/media/libaaudio/src
-LOCAL_SRC_FILES:= test_block_adapter.cpp
-LOCAL_SHARED_LIBRARIES := libaaudio
-LOCAL_MODULE := test_block_adapter
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-    frameworks/av/media/libaaudio/include \
-    frameworks/av/media/libaaudio/src \
-    frameworks/av/media/libaaudio/examples
-LOCAL_SRC_FILES:= test_timestamps.cpp
-LOCAL_SHARED_LIBRARIES := libaaudio
-LOCAL_MODULE := test_timestamps
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-    frameworks/av/media/libaaudio/include \
-    frameworks/av/media/libaaudio/src
-LOCAL_SRC_FILES:= test_linear_ramp.cpp
-LOCAL_SHARED_LIBRARIES := libaaudio
-LOCAL_MODULE := test_linear_ramp
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-    frameworks/av/media/libaaudio/include \
-    frameworks/av/media/libaaudio/src
-LOCAL_SRC_FILES:= test_open_params.cpp
-LOCAL_SHARED_LIBRARIES := libaaudio libbinder libcutils libutils
-LOCAL_MODULE := test_open_params
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-    frameworks/av/media/libaaudio/include \
-    frameworks/av/media/libaaudio/src
-LOCAL_SRC_FILES:= test_no_close.cpp
-LOCAL_SHARED_LIBRARIES := libaaudio libbinder libcutils libutils
-LOCAL_MODULE := test_no_close
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-    frameworks/av/media/libaaudio/include \
-    frameworks/av/media/libaaudio/src
-LOCAL_SRC_FILES:= test_recovery.cpp
-LOCAL_SHARED_LIBRARIES := libaaudio libbinder libcutils libutils
-LOCAL_MODULE := test_aaudio_recovery
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := \
-    $(call include-path-for, audio-utils) \
-    frameworks/av/media/libaaudio/include \
-    frameworks/av/media/libaaudio/src
-LOCAL_SRC_FILES:= test_n_streams.cpp
-LOCAL_SHARED_LIBRARIES := libaaudio libbinder libcutils libutils
-LOCAL_MODULE := test_n_streams
-include $(BUILD_NATIVE_TEST)
diff --git a/media/libaaudio/tests/test_n_streams.cpp b/media/libaaudio/tests/test_n_streams.cpp
index 271d024..e2d4a82 100644
--- a/media/libaaudio/tests/test_n_streams.cpp
+++ b/media/libaaudio/tests/test_n_streams.cpp
@@ -71,7 +71,6 @@
 
     AAudioStreamBuilder_delete(aaudioBuilder);
 
-finish:
     return result;
 }
 
diff --git a/media/libaaudio/tests/test_open_params.cpp b/media/libaaudio/tests/test_open_params.cpp
index 01b8799..3451242 100644
--- a/media/libaaudio/tests/test_open_params.cpp
+++ b/media/libaaudio/tests/test_open_params.cpp
@@ -25,21 +25,6 @@
 
 #include <gtest/gtest.h>
 
-static const char *getSharingModeText(aaudio_sharing_mode_t mode) {
-    const char *modeText = "unknown";
-    switch (mode) {
-    case AAUDIO_SHARING_MODE_EXCLUSIVE:
-        modeText = "EXCLUSIVE";
-        break;
-    case AAUDIO_SHARING_MODE_SHARED:
-        modeText = "SHARED";
-        break;
-    default:
-        break;
-    }
-    return modeText;
-}
-
 // Callback function that fills the audio output buffer.
 aaudio_data_callback_result_t MyDataCallbackProc(
         AAudioStream *stream,
@@ -67,7 +52,6 @@
     int32_t actualChannelCount = 0;
     int32_t actualSampleRate = 0;
     aaudio_format_t actualDataFormat = AAUDIO_FORMAT_UNSPECIFIED;
-    aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
     aaudio_direction_t actualDirection;
 
     AAudioStreamBuilder *aaudioBuilder = nullptr;
diff --git a/media/libaaudio/tests/test_recovery.cpp b/media/libaaudio/tests/test_recovery.cpp
index 7268a30..6e89f83 100644
--- a/media/libaaudio/tests/test_recovery.cpp
+++ b/media/libaaudio/tests/test_recovery.cpp
@@ -23,24 +23,9 @@
 
 #define DEFAULT_TIMEOUT_NANOS  ((int64_t)1000000000)
 
-static const char *getSharingModeText(aaudio_sharing_mode_t mode) {
-    const char *modeText = "unknown";
-    switch (mode) {
-        case AAUDIO_SHARING_MODE_EXCLUSIVE:
-            modeText = "EXCLUSIVE";
-            break;
-        case AAUDIO_SHARING_MODE_SHARED:
-            modeText = "SHARED";
-            break;
-        default:
-            break;
-    }
-    return modeText;
-}
-
 int main(int argc, char **argv) {
     (void) argc;
-    (void *)argv;
+    (void) argv;
 
     aaudio_result_t result = AAUDIO_OK;
 
@@ -52,7 +37,6 @@
     int32_t actualChannelCount = 0;
     int32_t actualSampleRate = 0;
     aaudio_format_t actualDataFormat = AAUDIO_FORMAT_PCM_FLOAT;
-    aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
 
     AAudioStreamBuilder *aaudioBuilder = nullptr;
     AAudioStream *aaudioStream = nullptr;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 3529d2c..c6622cd 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1391,14 +1391,14 @@
 
         bool useCaseAllowed = sharedBuffer || transferAllowed;
         if (!useCaseAllowed) {
-            ALOGW("AUDIO_OUTPUT_FLAG_FAST denied, not shared buffer and transfer = %s",
+            ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client, not shared buffer and transfer = %s",
                   convertTransferToText(mTransfer));
         }
 
         // sample rates must also match
         bool sampleRateAllowed = mSampleRate == mAfSampleRate;
         if (!sampleRateAllowed) {
-            ALOGW("AUDIO_OUTPUT_FLAG_FAST denied, rates do not match %u Hz, require %u Hz",
+            ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client, sample rate %u Hz but HAL needs %u Hz",
                   mSampleRate, mAfSampleRate);
         }
 
@@ -1576,6 +1576,15 @@
             // or at least triple-buffering if there is sample rate conversion
             const int nBuffering = mOriginalSampleRate == mAfSampleRate ? 2 : 3;
             maxNotificationFrames = frameCount / nBuffering;
+            // If client requested a fast track but this was denied, then use the smaller maximum.
+            // FMS_20 is the minimum task wakeup period in ms for which CFS operates reliably.
+#define FMS_20 20   // FIXME share a common declaration with the same symbol in Threads.cpp
+            if (mOrigFlags & AUDIO_OUTPUT_FLAG_FAST) {
+                size_t maxNotificationFramesFastDenied = FMS_20 * mSampleRate / 1000;
+                if (maxNotificationFrames > maxNotificationFramesFastDenied) {
+                    maxNotificationFrames = maxNotificationFramesFastDenied;
+                }
+            }
         }
         if (mNotificationFramesAct == 0 || mNotificationFramesAct > maxNotificationFrames) {
             if (mNotificationFramesAct == 0) {
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index 3c43a72..a8a7b82 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -23,6 +23,7 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
+#include <binder/PermissionCache.h>
 #include <media/IMediaExtractor.h>
 #include <media/stagefright/MetaData.h>
 
@@ -323,13 +324,21 @@
 
 status_t dumpExtractors(int fd, const Vector<String16>&) {
     String8 out;
-    out.append("Recent extractors, most recent first:\n");
-    {
-        Mutex::Autolock lock(sExtractorsLock);
-        for (size_t i = 0; i < sExtractors.size(); i++) {
-            const ExtractorInstance &instance = sExtractors.itemAt(i);
-            out.append("  ");
-            out.append(instance.toString());
+    const IPCThreadState* ipc = IPCThreadState::self();
+    const int pid = ipc->getCallingPid();
+    const int uid = ipc->getCallingUid();
+    if (!PermissionCache::checkPermission(String16("android.permission.DUMP"), pid, uid)) {
+        out.appendFormat("Permission Denial: "
+                "can't dump MediaExtractor from pid=%d, uid=%d\n", pid, uid);
+    } else {
+        out.append("Recent extractors, most recent first:\n");
+        {
+            Mutex::Autolock lock(sExtractorsLock);
+            for (size_t i = 0; i < sExtractors.size(); i++) {
+                const ExtractorInstance &instance = sExtractors.itemAt(i);
+                out.append("  ");
+                out.append(instance.toString());
+            }
         }
     }
     write(fd, out.string(), out.size());
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.bp b/media/libstagefright/codecs/amrnb/dec/Android.bp
index d266dc2..b493e21 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.bp
+++ b/media/libstagefright/codecs/amrnb/dec/Android.bp
@@ -114,6 +114,8 @@
 
     srcs: ["test/amrnbdec_test.cpp"],
 
+    cflags: ["-Wall", "-Werror"],
+
     local_include_dirs: ["src"],
 
     static_libs: [
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.bp b/media/libstagefright/codecs/amrnb/enc/Android.bp
index 6dc2dc1..1e8fd31 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.bp
+++ b/media/libstagefright/codecs/amrnb/enc/Android.bp
@@ -126,6 +126,8 @@
 
     srcs: ["test/amrnb_enc_test.cpp"],
 
+    cflags: ["-Wall", "-Werror"],
+
     local_include_dirs: ["src"],
 
     static_libs: ["libstagefright_amrnbenc"],
diff --git a/media/libstagefright/codecs/amrwb/Android.bp b/media/libstagefright/codecs/amrwb/Android.bp
index b932ccc..14a73d6 100644
--- a/media/libstagefright/codecs/amrwb/Android.bp
+++ b/media/libstagefright/codecs/amrwb/Android.bp
@@ -69,6 +69,8 @@
 
     srcs: ["test/amrwbdec_test.cpp"],
 
+    cflags: ["-Wall", "-Werror"],
+
     static_libs: [
         "libstagefright_amrwbdec",
         "libsndfile",
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp
index d52fed3..81b3f69 100644
--- a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.bp
@@ -4,6 +4,8 @@
 
     srcs: ["AMRWB_E_SAMPLE.c"],
 
+    cflags: ["-Wall", "-Werror"],
+
     arch: {
         arm: {
             instruction_set: "arm",
diff --git a/media/libstagefright/codecs/avcdec/Android.bp b/media/libstagefright/codecs/avcdec/Android.bp
index 1f43803..34db19b 100644
--- a/media/libstagefright/codecs/avcdec/Android.bp
+++ b/media/libstagefright/codecs/avcdec/Android.bp
@@ -8,6 +8,12 @@
     static_libs: ["libavcdec"],
     srcs: ["SoftAVCDec.cpp"],
 
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-variable",
+    ],
+
     include_dirs: [
         "external/libavc/decoder",
         "external/libavc/common",
diff --git a/media/libstagefright/codecs/avcenc/Android.bp b/media/libstagefright/codecs/avcenc/Android.bp
index 66507a7..5203126 100644
--- a/media/libstagefright/codecs/avcenc/Android.bp
+++ b/media/libstagefright/codecs/avcenc/Android.bp
@@ -33,6 +33,11 @@
         },
     },
 
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-variable",
+    ],
     ldflags: ["-Wl,-Bsymbolic"],
     compile_multilib: "32",
 }
diff --git a/media/libstagefright/codecs/hevcdec/Android.bp b/media/libstagefright/codecs/hevcdec/Android.bp
index 7fa74d4..d9a5ee3 100644
--- a/media/libstagefright/codecs/hevcdec/Android.bp
+++ b/media/libstagefright/codecs/hevcdec/Android.bp
@@ -8,6 +8,12 @@
     static_libs: ["libhevcdec"],
     srcs: ["SoftHEVC.cpp"],
 
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-variable",
+    ],
+
     include_dirs: [
         "external/libhevc/decoder",
         "external/libhevc/common",
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
index 640718d..a95b807 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/Android.bp
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.bp
@@ -112,6 +112,8 @@
         "-DOSCL_EXPORT_REF=",
         "-DOSCL_IMPORT_REF=",
         "-DBX_RC",
+        "-Wall",
+        "-Werror",
     ],
 
     sanitize: {
diff --git a/media/libstagefright/codecs/mp3dec/Android.bp b/media/libstagefright/codecs/mp3dec/Android.bp
index 273fa31..c554a99 100644
--- a/media/libstagefright/codecs/mp3dec/Android.bp
+++ b/media/libstagefright/codecs/mp3dec/Android.bp
@@ -128,6 +128,8 @@
         "test/mp3reader.cpp",
     ],
 
+    cflags: ["-Wall", "-Werror"],
+
     local_include_dirs: [
         "src",
         "include",
diff --git a/media/libstagefright/codecs/mpeg2dec/Android.bp b/media/libstagefright/codecs/mpeg2dec/Android.bp
index 15fdde7..9590e9f 100644
--- a/media/libstagefright/codecs/mpeg2dec/Android.bp
+++ b/media/libstagefright/codecs/mpeg2dec/Android.bp
@@ -8,6 +8,12 @@
     static_libs: ["libmpeg2dec"],
     srcs: ["SoftMPEG2.cpp"],
 
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-variable",
+    ],
+
     include_dirs: [
         "external/libmpeg2/decoder",
         "external/libmpeg2/common",
diff --git a/media/libstagefright/codecs/on2/enc/Android.bp b/media/libstagefright/codecs/on2/enc/Android.bp
index 741774c..5a52225 100644
--- a/media/libstagefright/codecs/on2/enc/Android.bp
+++ b/media/libstagefright/codecs/on2/enc/Android.bp
@@ -11,6 +11,8 @@
         "SoftVP9Encoder.cpp",
     ],
 
+    cflags: ["-Wall", "-Werror"],
+
     include_dirs: [
         "frameworks/av/media/libstagefright/include",
         "frameworks/native/include/media/openmax",
diff --git a/media/libstagefright/codecs/on2/h264dec/Android.bp b/media/libstagefright/codecs/on2/h264dec/Android.bp
index 6d558b6..0984283 100644
--- a/media/libstagefright/codecs/on2/h264dec/Android.bp
+++ b/media/libstagefright/codecs/on2/h264dec/Android.bp
@@ -96,6 +96,8 @@
         },
     },
 
+    cflags: ["-Wall", "-Werror"],
+
     include_dirs: [
         "frameworks/av/media/libstagefright/include",
         "frameworks/native/include/media/openmax",
@@ -133,5 +135,7 @@
 
     srcs: ["source/DecTestBench.c"],
 
+    cflags: ["-Wall", "-Werror"],
+
     shared_libs: ["libstagefright_soft_h264dec"],
 }
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 4b38906..462eff6 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -1434,6 +1434,14 @@
                 continue;
         }
 
+        const char *language = track->GetLanguage();
+        if (language != NULL) {
+           char lang[4];
+           strncpy(lang, language, 3);
+           lang[3] = '\0';
+           meta->setCString(kKeyMediaLanguage, lang);
+        }
+
         if (err != OK) {
             ALOGE("skipping track, codec specific data was malformed.");
             continue;
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index d4cdf69..bd3c1c6 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -124,6 +124,7 @@
             cfi: true,
         },
     },
+    cflags: ["-Wall", "-Werror"],
 }
 
 //###############################################################################
diff --git a/media/mtp/Android.bp b/media/mtp/Android.bp
index 543ad5c..acea373 100644
--- a/media/mtp/Android.bp
+++ b/media/mtp/Android.bp
@@ -19,6 +19,7 @@
     srcs: [
         "MtpDataPacket.cpp",
         "MtpDebug.cpp",
+        "MtpDescriptors.cpp",
         "MtpDevHandle.cpp",
         "MtpDevice.cpp",
         "MtpDeviceInfo.cpp",
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
index c7021df..2395f4f 100644
--- a/media/mtp/MtpDatabase.h
+++ b/media/mtp/MtpDatabase.h
@@ -104,7 +104,7 @@
     virtual MtpProperty*            getDevicePropertyDesc(MtpDeviceProperty property) = 0;
 
     virtual MtpResponseCode         moveObject(MtpObjectHandle handle, MtpObjectHandle newParent,
-                                            MtpString& newPath) = 0;
+                                            MtpStorageID newStorage, MtpString& newPath) = 0;
 
     virtual void                    sessionStarted() = 0;
 
diff --git a/media/mtp/MtpDescriptors.cpp b/media/mtp/MtpDescriptors.cpp
new file mode 100644
index 0000000..d9b6060
--- /dev/null
+++ b/media/mtp/MtpDescriptors.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MtpDescriptors.h"
+
+namespace android {
+
+const struct usb_interface_descriptor mtp_interface_desc = {
+    .bLength = USB_DT_INTERFACE_SIZE,
+    .bDescriptorType = USB_DT_INTERFACE,
+    .bInterfaceNumber = 0,
+    .bNumEndpoints = 3,
+    .bInterfaceClass = USB_CLASS_STILL_IMAGE,
+    .bInterfaceSubClass = 1,
+    .bInterfaceProtocol = 1,
+    .iInterface = 1,
+};
+
+const struct usb_interface_descriptor ptp_interface_desc = {
+    .bLength = USB_DT_INTERFACE_SIZE,
+    .bDescriptorType = USB_DT_INTERFACE,
+    .bInterfaceNumber = 0,
+    .bNumEndpoints = 3,
+    .bInterfaceClass = USB_CLASS_STILL_IMAGE,
+    .bInterfaceSubClass = 1,
+    .bInterfaceProtocol = 1,
+};
+
+const struct usb_endpoint_descriptor_no_audio fs_sink = {
+    .bLength = USB_DT_ENDPOINT_SIZE,
+    .bDescriptorType = USB_DT_ENDPOINT,
+    .bEndpointAddress = 1 | USB_DIR_IN,
+    .bmAttributes = USB_ENDPOINT_XFER_BULK,
+    .wMaxPacketSize = MAX_PACKET_SIZE_FS,
+};
+
+const struct usb_endpoint_descriptor_no_audio fs_source = {
+    .bLength = USB_DT_ENDPOINT_SIZE,
+    .bDescriptorType = USB_DT_ENDPOINT,
+    .bEndpointAddress = 2 | USB_DIR_OUT,
+    .bmAttributes = USB_ENDPOINT_XFER_BULK,
+    .wMaxPacketSize = MAX_PACKET_SIZE_FS,
+};
+
+const struct usb_endpoint_descriptor_no_audio intr = {
+    .bLength = USB_DT_ENDPOINT_SIZE,
+    .bDescriptorType = USB_DT_ENDPOINT,
+    .bEndpointAddress = 3 | USB_DIR_IN,
+    .bmAttributes = USB_ENDPOINT_XFER_INT,
+    .wMaxPacketSize = MAX_PACKET_SIZE_EV,
+    .bInterval = 6,
+};
+
+const struct usb_endpoint_descriptor_no_audio hs_sink = {
+    .bLength = USB_DT_ENDPOINT_SIZE,
+    .bDescriptorType = USB_DT_ENDPOINT,
+    .bEndpointAddress = 1 | USB_DIR_IN,
+    .bmAttributes = USB_ENDPOINT_XFER_BULK,
+    .wMaxPacketSize = MAX_PACKET_SIZE_HS,
+};
+
+const struct usb_endpoint_descriptor_no_audio hs_source = {
+    .bLength = USB_DT_ENDPOINT_SIZE,
+    .bDescriptorType = USB_DT_ENDPOINT,
+    .bEndpointAddress = 2 | USB_DIR_OUT,
+    .bmAttributes = USB_ENDPOINT_XFER_BULK,
+    .wMaxPacketSize = MAX_PACKET_SIZE_HS,
+};
+
+const struct usb_endpoint_descriptor_no_audio ss_sink = {
+    .bLength = USB_DT_ENDPOINT_SIZE,
+    .bDescriptorType = USB_DT_ENDPOINT,
+    .bEndpointAddress = 1 | USB_DIR_IN,
+    .bmAttributes = USB_ENDPOINT_XFER_BULK,
+    .wMaxPacketSize = MAX_PACKET_SIZE_SS,
+};
+
+const struct usb_endpoint_descriptor_no_audio ss_source = {
+    .bLength = USB_DT_ENDPOINT_SIZE,
+    .bDescriptorType = USB_DT_ENDPOINT,
+    .bEndpointAddress = 2 | USB_DIR_OUT,
+    .bmAttributes = USB_ENDPOINT_XFER_BULK,
+    .wMaxPacketSize = MAX_PACKET_SIZE_SS,
+};
+
+const struct usb_ss_ep_comp_descriptor ss_sink_comp = {
+    .bLength = sizeof(ss_sink_comp),
+    .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+    .bMaxBurst = 6,
+};
+
+const struct usb_ss_ep_comp_descriptor ss_source_comp = {
+    .bLength = sizeof(ss_source_comp),
+    .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+    .bMaxBurst = 6,
+};
+
+const struct usb_ss_ep_comp_descriptor ss_intr_comp = {
+    .bLength = sizeof(ss_intr_comp),
+    .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+};
+
+const struct func_desc mtp_fs_descriptors = {
+    .intf = mtp_interface_desc,
+    .sink = fs_sink,
+    .source = fs_source,
+    .intr = intr,
+};
+
+const struct func_desc mtp_hs_descriptors = {
+    .intf = mtp_interface_desc,
+    .sink = hs_sink,
+    .source = hs_source,
+    .intr = intr,
+};
+
+const struct ss_func_desc mtp_ss_descriptors = {
+    .intf = mtp_interface_desc,
+    .sink = ss_sink,
+    .sink_comp = ss_sink_comp,
+    .source = ss_source,
+    .source_comp = ss_source_comp,
+    .intr = intr,
+    .intr_comp = ss_intr_comp,
+};
+
+const struct func_desc ptp_fs_descriptors = {
+    .intf = ptp_interface_desc,
+    .sink = fs_sink,
+    .source = fs_source,
+    .intr = intr,
+};
+
+const struct func_desc ptp_hs_descriptors = {
+    .intf = ptp_interface_desc,
+    .sink = hs_sink,
+    .source = hs_source,
+    .intr = intr,
+};
+
+const struct ss_func_desc ptp_ss_descriptors = {
+    .intf = ptp_interface_desc,
+    .sink = ss_sink,
+    .sink_comp = ss_sink_comp,
+    .source = ss_source,
+    .source_comp = ss_source_comp,
+    .intr = intr,
+    .intr_comp = ss_intr_comp,
+};
+
+const struct functionfs_strings mtp_strings = {
+    .header = {
+        .magic = htole32(FUNCTIONFS_STRINGS_MAGIC),
+        .length = htole32(sizeof(mtp_strings)),
+        .str_count = htole32(1),
+        .lang_count = htole32(1),
+    },
+    .lang0 = {
+        .code = htole16(0x0409),
+        .str1 = STR_INTERFACE,
+    },
+};
+
+const struct usb_os_desc_header mtp_os_desc_header = {
+    .interface = htole32(1),
+    .dwLength = htole32(sizeof(usb_os_desc_header) + sizeof(usb_ext_compat_desc)),
+    .bcdVersion = htole16(1),
+    .wIndex = htole16(4),
+    .bCount = htole16(1),
+    .Reserved = htole16(0),
+};
+
+const struct usb_ext_compat_desc mtp_os_desc_compat = {
+    .bFirstInterfaceNumber = 0,
+    .Reserved1 = htole32(1),
+    .CompatibleID = { 'M', 'T', 'P' },
+    .SubCompatibleID = {0},
+    .Reserved2 = {0},
+};
+
+const struct usb_ext_compat_desc ptp_os_desc_compat = {
+    .bFirstInterfaceNumber = 0,
+    .Reserved1 = htole32(1),
+    .CompatibleID = { 'P', 'T', 'P' },
+    .SubCompatibleID = {0},
+    .Reserved2 = {0},
+};
+
+const struct desc_v2 mtp_desc_v2 = {
+    .header = {
+        .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2),
+        .length = htole32(sizeof(struct desc_v2)),
+        .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
+                 FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC,
+    },
+    .fs_count = 4,
+    .hs_count = 4,
+    .ss_count = 7,
+    .os_count = 1,
+    .fs_descs = mtp_fs_descriptors,
+    .hs_descs = mtp_hs_descriptors,
+    .ss_descs = mtp_ss_descriptors,
+    .os_header = mtp_os_desc_header,
+    .os_desc = mtp_os_desc_compat,
+};
+
+const struct desc_v2 ptp_desc_v2 = {
+    .header = {
+        .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2),
+        .length = htole32(sizeof(struct desc_v2)),
+        .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
+                 FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC,
+    },
+    .fs_count = 4,
+    .hs_count = 4,
+    .ss_count = 7,
+    .os_count = 1,
+    .fs_descs = ptp_fs_descriptors,
+    .hs_descs = ptp_hs_descriptors,
+    .ss_descs = ptp_ss_descriptors,
+    .os_header = mtp_os_desc_header,
+    .os_desc = ptp_os_desc_compat,
+};
+
+const struct desc_v1 mtp_desc_v1 = {
+    .header = {
+        .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC),
+        .length = htole32(sizeof(struct desc_v1)),
+        .fs_count = 4,
+        .hs_count = 4,
+    },
+    .fs_descs = mtp_fs_descriptors,
+    .hs_descs = mtp_hs_descriptors,
+};
+
+const struct desc_v1 ptp_desc_v1 = {
+    .header = {
+        .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC),
+        .length = htole32(sizeof(struct desc_v1)),
+        .fs_count = 4,
+        .hs_count = 4,
+    },
+    .fs_descs = ptp_fs_descriptors,
+    .hs_descs = ptp_hs_descriptors,
+};
+
+}; // namespace android
diff --git a/media/mtp/MtpDescriptors.h b/media/mtp/MtpDescriptors.h
new file mode 100644
index 0000000..cfc3930
--- /dev/null
+++ b/media/mtp/MtpDescriptors.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MTP_DESCRIPTORS_H
+#define MTP_DESCRIPTORS_H
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/functionfs.h>
+#include <sys/endian.h>
+
+namespace android {
+
+constexpr int MAX_PACKET_SIZE_FS = 64;
+constexpr int MAX_PACKET_SIZE_HS = 512;
+constexpr int MAX_PACKET_SIZE_SS = 1024;
+constexpr int MAX_PACKET_SIZE_EV = 28;
+
+struct func_desc {
+    struct usb_interface_descriptor intf;
+    struct usb_endpoint_descriptor_no_audio sink;
+    struct usb_endpoint_descriptor_no_audio source;
+    struct usb_endpoint_descriptor_no_audio intr;
+} __attribute__((packed));
+
+struct ss_func_desc {
+    struct usb_interface_descriptor intf;
+    struct usb_endpoint_descriptor_no_audio sink;
+    struct usb_ss_ep_comp_descriptor sink_comp;
+    struct usb_endpoint_descriptor_no_audio source;
+    struct usb_ss_ep_comp_descriptor source_comp;
+    struct usb_endpoint_descriptor_no_audio intr;
+    struct usb_ss_ep_comp_descriptor intr_comp;
+} __attribute__((packed));
+
+struct desc_v1 {
+    struct usb_functionfs_descs_head_v1 {
+        __le32 magic;
+        __le32 length;
+        __le32 fs_count;
+        __le32 hs_count;
+    } __attribute__((packed)) header;
+    struct func_desc fs_descs, hs_descs;
+} __attribute__((packed));
+
+struct desc_v2 {
+    struct usb_functionfs_descs_head_v2 header;
+    // The rest of the structure depends on the flags in the header.
+    __le32 fs_count;
+    __le32 hs_count;
+    __le32 ss_count;
+    __le32 os_count;
+    struct func_desc fs_descs, hs_descs;
+    struct ss_func_desc ss_descs;
+    struct usb_os_desc_header os_header;
+    struct usb_ext_compat_desc os_desc;
+} __attribute__((packed));
+
+// OS descriptor contents should not be changed. See b/64790536.
+static_assert(sizeof(struct desc_v2) == sizeof(usb_functionfs_descs_head_v2) +
+        16 + 2 * sizeof(struct func_desc) + sizeof(struct ss_func_desc) +
+        sizeof(usb_os_desc_header) + sizeof(usb_ext_compat_desc),
+        "Size of mtp descriptor is incorrect!");
+
+#define STR_INTERFACE "MTP"
+struct functionfs_lang {
+    __le16 code;
+    char str1[sizeof(STR_INTERFACE)];
+} __attribute__((packed));
+
+struct functionfs_strings {
+    struct usb_functionfs_strings_head header;
+    struct functionfs_lang lang0;
+} __attribute__((packed));
+
+extern const struct desc_v2 mtp_desc_v2;
+extern const struct desc_v2 ptp_desc_v2;
+extern const struct desc_v1 mtp_desc_v1;
+extern const struct desc_v1 ptp_desc_v1;
+extern const struct functionfs_strings mtp_strings;
+
+}; // namespace android
+
+#endif // MTP_DESCRIPTORS_H
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 965985d..217e0c9 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -20,13 +20,10 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/functionfs.h>
 #include <memory>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/endian.h>
 #include <sys/eventfd.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
@@ -36,6 +33,7 @@
 #include <unistd.h>
 
 #include "PosixAsyncIO.h"
+#include "MtpDescriptors.h"
 #include "MtpFfsHandle.h"
 #include "mtp.h"
 
@@ -45,11 +43,6 @@
 constexpr char FFS_MTP_EP_OUT[] = "/dev/usb-ffs/mtp/ep2";
 constexpr char FFS_MTP_EP_INTR[] = "/dev/usb-ffs/mtp/ep3";
 
-constexpr int MAX_PACKET_SIZE_FS = 64;
-constexpr int MAX_PACKET_SIZE_HS = 512;
-constexpr int MAX_PACKET_SIZE_SS = 1024;
-constexpr int MAX_PACKET_SIZE_EV = 28;
-
 constexpr unsigned AIO_BUFS_MAX = 128;
 constexpr unsigned AIO_BUF_LEN = 16384;
 
@@ -61,234 +54,6 @@
 
 struct timespec ZERO_TIMEOUT = { 0, 0 };
 
-struct func_desc {
-    struct usb_interface_descriptor intf;
-    struct usb_endpoint_descriptor_no_audio sink;
-    struct usb_endpoint_descriptor_no_audio source;
-    struct usb_endpoint_descriptor_no_audio intr;
-} __attribute__((packed));
-
-struct ss_func_desc {
-    struct usb_interface_descriptor intf;
-    struct usb_endpoint_descriptor_no_audio sink;
-    struct usb_ss_ep_comp_descriptor sink_comp;
-    struct usb_endpoint_descriptor_no_audio source;
-    struct usb_ss_ep_comp_descriptor source_comp;
-    struct usb_endpoint_descriptor_no_audio intr;
-    struct usb_ss_ep_comp_descriptor intr_comp;
-} __attribute__((packed));
-
-struct desc_v1 {
-    struct usb_functionfs_descs_head_v1 {
-        __le32 magic;
-        __le32 length;
-        __le32 fs_count;
-        __le32 hs_count;
-    } __attribute__((packed)) header;
-    struct func_desc fs_descs, hs_descs;
-} __attribute__((packed));
-
-struct desc_v2 {
-    struct usb_functionfs_descs_head_v2 header;
-    // The rest of the structure depends on the flags in the header.
-    __le32 fs_count;
-    __le32 hs_count;
-    __le32 ss_count;
-    __le32 os_count;
-    struct func_desc fs_descs, hs_descs;
-    struct ss_func_desc ss_descs;
-    struct usb_os_desc_header os_header;
-    struct usb_ext_compat_desc os_desc;
-} __attribute__((packed));
-
-const struct usb_interface_descriptor mtp_interface_desc = {
-    .bLength = USB_DT_INTERFACE_SIZE,
-    .bDescriptorType = USB_DT_INTERFACE,
-    .bInterfaceNumber = 0,
-    .bNumEndpoints = 3,
-    .bInterfaceClass = USB_CLASS_STILL_IMAGE,
-    .bInterfaceSubClass = 1,
-    .bInterfaceProtocol = 1,
-    .iInterface = 1,
-};
-
-const struct usb_interface_descriptor ptp_interface_desc = {
-    .bLength = USB_DT_INTERFACE_SIZE,
-    .bDescriptorType = USB_DT_INTERFACE,
-    .bInterfaceNumber = 0,
-    .bNumEndpoints = 3,
-    .bInterfaceClass = USB_CLASS_STILL_IMAGE,
-    .bInterfaceSubClass = 1,
-    .bInterfaceProtocol = 1,
-};
-
-const struct usb_endpoint_descriptor_no_audio fs_sink = {
-    .bLength = USB_DT_ENDPOINT_SIZE,
-    .bDescriptorType = USB_DT_ENDPOINT,
-    .bEndpointAddress = 1 | USB_DIR_IN,
-    .bmAttributes = USB_ENDPOINT_XFER_BULK,
-    .wMaxPacketSize = MAX_PACKET_SIZE_FS,
-};
-
-const struct usb_endpoint_descriptor_no_audio fs_source = {
-    .bLength = USB_DT_ENDPOINT_SIZE,
-    .bDescriptorType = USB_DT_ENDPOINT,
-    .bEndpointAddress = 2 | USB_DIR_OUT,
-    .bmAttributes = USB_ENDPOINT_XFER_BULK,
-    .wMaxPacketSize = MAX_PACKET_SIZE_FS,
-};
-
-const struct usb_endpoint_descriptor_no_audio intr = {
-    .bLength = USB_DT_ENDPOINT_SIZE,
-    .bDescriptorType = USB_DT_ENDPOINT,
-    .bEndpointAddress = 3 | USB_DIR_IN,
-    .bmAttributes = USB_ENDPOINT_XFER_INT,
-    .wMaxPacketSize = MAX_PACKET_SIZE_EV,
-    .bInterval = 6,
-};
-
-const struct usb_endpoint_descriptor_no_audio hs_sink = {
-    .bLength = USB_DT_ENDPOINT_SIZE,
-    .bDescriptorType = USB_DT_ENDPOINT,
-    .bEndpointAddress = 1 | USB_DIR_IN,
-    .bmAttributes = USB_ENDPOINT_XFER_BULK,
-    .wMaxPacketSize = MAX_PACKET_SIZE_HS,
-};
-
-const struct usb_endpoint_descriptor_no_audio hs_source = {
-    .bLength = USB_DT_ENDPOINT_SIZE,
-    .bDescriptorType = USB_DT_ENDPOINT,
-    .bEndpointAddress = 2 | USB_DIR_OUT,
-    .bmAttributes = USB_ENDPOINT_XFER_BULK,
-    .wMaxPacketSize = MAX_PACKET_SIZE_HS,
-};
-
-const struct usb_endpoint_descriptor_no_audio ss_sink = {
-    .bLength = USB_DT_ENDPOINT_SIZE,
-    .bDescriptorType = USB_DT_ENDPOINT,
-    .bEndpointAddress = 1 | USB_DIR_IN,
-    .bmAttributes = USB_ENDPOINT_XFER_BULK,
-    .wMaxPacketSize = MAX_PACKET_SIZE_SS,
-};
-
-const struct usb_endpoint_descriptor_no_audio ss_source = {
-    .bLength = USB_DT_ENDPOINT_SIZE,
-    .bDescriptorType = USB_DT_ENDPOINT,
-    .bEndpointAddress = 2 | USB_DIR_OUT,
-    .bmAttributes = USB_ENDPOINT_XFER_BULK,
-    .wMaxPacketSize = MAX_PACKET_SIZE_SS,
-};
-
-const struct usb_ss_ep_comp_descriptor ss_sink_comp = {
-    .bLength = sizeof(ss_sink_comp),
-    .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
-    .bMaxBurst = 6,
-};
-
-const struct usb_ss_ep_comp_descriptor ss_source_comp = {
-    .bLength = sizeof(ss_source_comp),
-    .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
-    .bMaxBurst = 6,
-};
-
-const struct usb_ss_ep_comp_descriptor ss_intr_comp = {
-    .bLength = sizeof(ss_intr_comp),
-    .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
-};
-
-const struct func_desc mtp_fs_descriptors = {
-    .intf = mtp_interface_desc,
-    .sink = fs_sink,
-    .source = fs_source,
-    .intr = intr,
-};
-
-const struct func_desc mtp_hs_descriptors = {
-    .intf = mtp_interface_desc,
-    .sink = hs_sink,
-    .source = hs_source,
-    .intr = intr,
-};
-
-const struct ss_func_desc mtp_ss_descriptors = {
-    .intf = mtp_interface_desc,
-    .sink = ss_sink,
-    .sink_comp = ss_sink_comp,
-    .source = ss_source,
-    .source_comp = ss_source_comp,
-    .intr = intr,
-    .intr_comp = ss_intr_comp,
-};
-
-const struct func_desc ptp_fs_descriptors = {
-    .intf = ptp_interface_desc,
-    .sink = fs_sink,
-    .source = fs_source,
-    .intr = intr,
-};
-
-const struct func_desc ptp_hs_descriptors = {
-    .intf = ptp_interface_desc,
-    .sink = hs_sink,
-    .source = hs_source,
-    .intr = intr,
-};
-
-const struct ss_func_desc ptp_ss_descriptors = {
-    .intf = ptp_interface_desc,
-    .sink = ss_sink,
-    .sink_comp = ss_sink_comp,
-    .source = ss_source,
-    .source_comp = ss_source_comp,
-    .intr = intr,
-    .intr_comp = ss_intr_comp,
-};
-
-#define STR_INTERFACE "MTP"
-const struct {
-    struct usb_functionfs_strings_head header;
-    struct {
-        __le16 code;
-        const char str1[sizeof(STR_INTERFACE)];
-    } __attribute__((packed)) lang0;
-} __attribute__((packed)) strings = {
-    .header = {
-        .magic = htole32(FUNCTIONFS_STRINGS_MAGIC),
-        .length = htole32(sizeof(strings)),
-        .str_count = htole32(1),
-        .lang_count = htole32(1),
-    },
-    .lang0 = {
-        .code = htole16(0x0409),
-        .str1 = STR_INTERFACE,
-    },
-};
-
-struct usb_os_desc_header mtp_os_desc_header = {
-    .interface = htole32(1),
-    .dwLength = htole32(sizeof(usb_os_desc_header) + sizeof(usb_ext_compat_desc)),
-    .bcdVersion = htole16(1),
-    .wIndex = htole16(4),
-    .bCount = htole16(1),
-    .Reserved = htole16(0),
-};
-
-struct usb_ext_compat_desc mtp_os_desc_compat = {
-    .bFirstInterfaceNumber = 0,
-    .Reserved1 = htole32(1),
-    .CompatibleID = { 'M', 'T', 'P' },
-    .SubCompatibleID = {0},
-    .Reserved2 = {0},
-};
-
-struct usb_ext_compat_desc ptp_os_desc_compat = {
-    .bFirstInterfaceNumber = 0,
-    .Reserved1 = htole32(1),
-    .CompatibleID = { 'P', 'T', 'P' },
-    .SubCompatibleID = {0},
-    .Reserved2 = {0},
-};
-
 struct mtp_device_status {
     uint16_t  wLength;
     uint16_t  wCode;
@@ -357,58 +122,38 @@
 }
 
 bool MtpFfsHandle::initFunctionfs() {
-    ssize_t ret;
-    struct desc_v1 v1_descriptor;
-    struct desc_v2 v2_descriptor;
-
-    v2_descriptor.header.magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
-    v2_descriptor.header.length = htole32(sizeof(v2_descriptor));
-    v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
-                                 FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC;
-    v2_descriptor.fs_count = 4;
-    v2_descriptor.hs_count = 4;
-    v2_descriptor.ss_count = 7;
-    v2_descriptor.os_count = 1;
-    v2_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
-    v2_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
-    v2_descriptor.ss_descs = mPtp ? ptp_ss_descriptors : mtp_ss_descriptors;
-    v2_descriptor.os_header = mtp_os_desc_header;
-    v2_descriptor.os_desc = mPtp ? ptp_os_desc_compat : mtp_os_desc_compat;
-
     if (mControl < 0) { // might have already done this before
         mControl.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP0, O_RDWR)));
         if (mControl < 0) {
             PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open control endpoint";
-            goto err;
+            return false;
         }
-
-        ret = TEMP_FAILURE_RETRY(::write(mControl, &v2_descriptor, sizeof(v2_descriptor)));
-        if (ret < 0) {
-            v1_descriptor.header.magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC);
-            v1_descriptor.header.length = htole32(sizeof(v1_descriptor));
-            v1_descriptor.header.fs_count = 4;
-            v1_descriptor.header.hs_count = 4;
-            v1_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
-            v1_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
-            PLOG(ERROR) << FFS_MTP_EP0 << "Switching to V1 descriptor format";
-            ret = TEMP_FAILURE_RETRY(::write(mControl, &v1_descriptor, sizeof(v1_descriptor)));
-            if (ret < 0) {
-                PLOG(ERROR) << FFS_MTP_EP0 << "Writing descriptors failed";
-                goto err;
-            }
-        }
-        ret = TEMP_FAILURE_RETRY(::write(mControl, &strings, sizeof(strings)));
-        if (ret < 0) {
-            PLOG(ERROR) << FFS_MTP_EP0 << "Writing strings failed";
-            goto err;
+        if (!writeDescriptors()) {
+            closeConfig();
+            return false;
         }
     }
-
     return true;
+}
 
-err:
-    closeConfig();
-    return false;
+bool MtpFfsHandle::writeDescriptors() {
+    ssize_t ret = TEMP_FAILURE_RETRY(::write(mControl,
+                &(mPtp ? ptp_desc_v2 : mtp_desc_v2), sizeof(desc_v2)));
+    if (ret < 0) {
+        PLOG(ERROR) << FFS_MTP_EP0 << "Switching to V1 descriptor format";
+        ret = TEMP_FAILURE_RETRY(::write(mControl,
+                    &(mPtp ? ptp_desc_v1 : mtp_desc_v1), sizeof(desc_v1)));
+        if (ret < 0) {
+            PLOG(ERROR) << FFS_MTP_EP0 << "Writing descriptors failed";
+            return false;
+        }
+    }
+    ret = TEMP_FAILURE_RETRY(::write(mControl, &mtp_strings, sizeof(mtp_strings)));
+    if (ret < 0) {
+        PLOG(ERROR) << FFS_MTP_EP0 << "Writing strings failed";
+        return false;
+    }
+    return true;
 }
 
 void MtpFfsHandle::closeConfig() {
@@ -566,7 +311,7 @@
 
 int MtpFfsHandle::configure(bool usePtp) {
     // Wait till previous server invocation has closed
-    if (!mLock.try_lock_for(std::chrono::milliseconds(1000))) {
+    if (!mLock.try_lock_for(std::chrono::milliseconds(300))) {
         LOG(ERROR) << "MtpServer was unable to get configure lock";
         return -1;
     }
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
index 2f90bd1..2347000 100644
--- a/media/mtp/MtpFfsHandle.h
+++ b/media/mtp/MtpFfsHandle.h
@@ -42,11 +42,14 @@
 };
 
 template <class T> class MtpFfsHandleTest;
+template <class T> class MtpFfsHandleTest_testControl_Test;
 
 class MtpFfsHandle : public IMtpHandle {
-    template <class T> friend class android::MtpFfsHandleTest;
+    template <class T> friend class MtpFfsHandleTest;
+    template <class T> friend class MtpFfsHandleTest_testControl_Test;
 protected:
     bool initFunctionfs();
+    bool writeDescriptors();
     void closeConfig();
     void closeEndpoints();
     void advise(int fd);
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 236f3a9..6080868 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <chrono>
 #include <dirent.h>
@@ -99,16 +100,12 @@
 };
 
 MtpServer::MtpServer(MtpDatabase* database, bool ptp,
-                    int fileGroup, int filePerm, int directoryPerm,
                     const MtpString& deviceInfoManufacturer,
                     const MtpString& deviceInfoModel,
                     const MtpString& deviceInfoDeviceVersion,
                     const MtpString& deviceInfoSerialNumber)
     :   mDatabase(database),
         mPtp(ptp),
-        mFileGroup(fileGroup),
-        mFilePermission(filePerm),
-        mDirectoryPermission(directoryPerm),
         mDeviceInfoManufacturer(deviceInfoManufacturer),
         mDeviceInfoModel(deviceInfoModel),
         mDeviceInfoDeviceVersion(deviceInfoDeviceVersion),
@@ -137,12 +134,11 @@
             sHandle = new MtpDevHandle();
         }
     }
-    if (sHandle->configure(usePtp)) {
-        ALOGE("Failed to configure Mtp driver!");
-        return -1;
-    }
+
+    int ret = sHandle->configure(usePtp);
+    if (ret) ALOGE("Failed to configure MTP driver!");
     android::base::SetProperty("sys.usb.ffs.mtp.ready", "1");
-    return 0;
+    return ret;
 }
 
 void MtpServer::addStorage(MtpStorage* storage) {
@@ -1002,12 +998,9 @@
     }
 
   if (format == MTP_FORMAT_ASSOCIATION) {
-        mode_t mask = umask(0);
-        int ret = mkdir((const char *)path, mDirectoryPermission);
-        umask(mask);
-        if (ret && ret != -EEXIST)
+        int ret = makeFolder((const char *)path);
+        if (ret)
             return MTP_RESPONSE_GENERAL_ERROR;
-        chown((const char *)path, getuid(), mFileGroup);
 
         // SendObject does not get sent for directories, so call endSendObject here instead
         mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK);
@@ -1068,29 +1061,34 @@
         path += "/";
     path += info.mName;
 
-    result = mDatabase->moveObject(objectHandle, parent, path);
-    if (result != MTP_RESPONSE_OK)
-        return result;
-
     if (info.mStorageID == storageID) {
         ALOGV("Moving file from %s to %s", (const char*)fromPath, (const char*)path);
         if (rename(fromPath, path)) {
-            ALOGE("rename() failed from %s to %s", (const char*)fromPath, (const char*)path);
+            PLOG(ERROR) << "rename() failed from " << fromPath << " to " << path;
             result = MTP_RESPONSE_GENERAL_ERROR;
         }
     } else {
         ALOGV("Moving across storages from %s to %s", (const char*)fromPath, (const char*)path);
-        if (copyFile(fromPath, path)) {
-            result = MTP_RESPONSE_GENERAL_ERROR;
+        if (format == MTP_FORMAT_ASSOCIATION) {
+            int ret = makeFolder((const char *)path);
+            ret += copyRecursive(fromPath, path);
+            if (ret) {
+                result = MTP_RESPONSE_GENERAL_ERROR;
+            } else {
+                deletePath(fromPath);
+            }
         } else {
-            deletePath(fromPath);
+            if (copyFile(fromPath, path)) {
+                result = MTP_RESPONSE_GENERAL_ERROR;
+            } else {
+                deletePath(fromPath);
+            }
         }
     }
 
     // If the move failed, undo the database change
-    if (result != MTP_RESPONSE_OK)
-        if (mDatabase->moveObject(objectHandle, info.mParent, fromPath) != MTP_RESPONSE_OK)
-            ALOGE("Couldn't undo failed move");
+    if (result == MTP_RESPONSE_OK)
+        result = mDatabase->moveObject(objectHandle, parent, storageID, path);
 
     return result;
 }
@@ -1148,8 +1146,15 @@
     }
 
     ALOGV("Copying file from %s to %s", (const char*)fromPath, (const char*)path);
-    if (copyFile(fromPath, path)) {
-        result = MTP_RESPONSE_GENERAL_ERROR;
+    if (format == MTP_FORMAT_ASSOCIATION) {
+        int ret = makeFolder((const char *)path);
+        if (ret) {
+            result = MTP_RESPONSE_GENERAL_ERROR;
+        }
+    } else {
+        if (copyFile(fromPath, path)) {
+            result = MTP_RESPONSE_GENERAL_ERROR;
+        }
     }
 
     mDatabase->endSendObject(path, handle, format, result);
@@ -1188,10 +1193,10 @@
         result = MTP_RESPONSE_GENERAL_ERROR;
         goto done;
     }
-    fchown(mfr.fd, getuid(), mFileGroup);
+    fchown(mfr.fd, getuid(), FILE_GROUP);
     // set permissions
     mask = umask(0);
-    fchmod(mfr.fd, mFilePermission);
+    fchmod(mfr.fd, FILE_PERM);
     umask(mask);
 
     if (initialData > 0) {
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index aafc753..0204b09 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -43,12 +43,6 @@
     // appear as a PTP device
     bool                mPtp;
 
-    // group to own new files and folders
-    int                 mFileGroup;
-    // permissions for new files and directories
-    int                 mFilePermission;
-    int                 mDirectoryPermission;
-
     // Manufacturer to report in DeviceInfo
     MtpString           mDeviceInfoManufacturer;
     // Model to report in DeviceInfo
@@ -105,7 +99,6 @@
 
 public:
                         MtpServer(MtpDatabase* database, bool ptp,
-                                    int fileGroup, int filePerm, int directoryPerm,
                                     const MtpString& deviceInfoManufacturer,
                                     const MtpString& deviceInfoModel,
                                     const MtpString& deviceInfoDeviceVersion,
diff --git a/media/mtp/MtpUtils.cpp b/media/mtp/MtpUtils.cpp
index 036ffe7..3f5648b 100644
--- a/media/mtp/MtpUtils.cpp
+++ b/media/mtp/MtpUtils.cpp
@@ -20,6 +20,7 @@
 #include <android-base/unique_fd.h>
 #include <dirent.h>
 #include <fcntl.h>
+#include <string>
 #include <sys/sendfile.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -29,6 +30,8 @@
 
 #include "MtpUtils.h"
 
+using namespace std;
+
 namespace android {
 
 constexpr unsigned long FILE_COPY_SIZE = 262144;
@@ -88,6 +91,60 @@
         tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
 }
 
+int makeFolder(const char *path) {
+    mode_t mask = umask(0);
+    int ret = mkdir((const char *)path, DIR_PERM);
+    umask(mask);
+    if (ret && ret != -EEXIST) {
+        PLOG(ERROR) << "Failed to create folder " << path;
+        ret = -1;
+    } else {
+        chown((const char *)path, getuid(), FILE_GROUP);
+    }
+    return ret;
+}
+
+/**
+ * Copies target path and all children to destination path.
+ *
+ * Returns 0 on success or a negative value indicating number of failures
+ */
+int copyRecursive(const char *fromPath, const char *toPath) {
+    int ret = 0;
+    string fromPathStr(fromPath);
+    string toPathStr(toPath);
+
+    DIR* dir = opendir(fromPath);
+    if (!dir) {
+        PLOG(ERROR) << "opendir " << fromPath << " failed";
+        return -1;
+    }
+    if (fromPathStr[fromPathStr.size()-1] != '/')
+        fromPathStr += '/';
+    if (toPathStr[toPathStr.size()-1] != '/')
+        toPathStr += '/';
+
+    struct dirent* entry;
+    while ((entry = readdir(dir))) {
+        const char* name = entry->d_name;
+
+        // ignore "." and ".."
+        if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
+            continue;
+        }
+        string oldFile = fromPathStr + name;
+        string newFile = toPathStr + name;
+
+        if (entry->d_type == DT_DIR) {
+            ret += makeFolder(newFile.c_str());
+            ret += copyRecursive(oldFile.c_str(), newFile.c_str());
+        } else {
+            ret += copyFile(oldFile.c_str(), newFile.c_str());
+        }
+    }
+    return ret;
+}
+
 int copyFile(const char *fromPath, const char *toPath) {
     auto start = std::chrono::steady_clock::now();
 
@@ -96,7 +153,7 @@
         PLOG(ERROR) << "Failed to open copy from " << fromPath;
         return -1;
     }
-    android::base::unique_fd toFd(open(toPath, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR));
+    android::base::unique_fd toFd(open(toPath, O_CREAT | O_WRONLY, FILE_PERM));
     if (toFd == -1) {
         PLOG(ERROR) << "Failed to open copy to " << toPath;
         return -1;
@@ -121,23 +178,17 @@
     }
     auto end = std::chrono::steady_clock::now();
     std::chrono::duration<double> diff = end - start;
-    LOG(INFO) << "Copied a file with MTP. Time: " << diff.count() << " s, Size: " << length <<
+    LOG(DEBUG) << "Copied a file with MTP. Time: " << diff.count() << " s, Size: " << length <<
         ", Rate: " << ((double) length) / diff.count() << " bytes/s";
+    chown(toPath, getuid(), FILE_GROUP);
     return ret == -1 ? -1 : 0;
 }
 
 void deleteRecursive(const char* path) {
-    char pathbuf[PATH_MAX];
-    size_t pathLength = strlen(path);
-    if (pathLength >= sizeof(pathbuf) - 1) {
-        LOG(ERROR) << "path too long: " << path;
+    string pathStr(path);
+    if (pathStr[pathStr.size()-1] != '/') {
+        pathStr += '/';
     }
-    strcpy(pathbuf, path);
-    if (pathbuf[pathLength - 1] != '/') {
-        pathbuf[pathLength++] = '/';
-    }
-    char* fileSpot = pathbuf + pathLength;
-    int pathRemaining = sizeof(pathbuf) - pathLength - 1;
 
     DIR* dir = opendir(path);
     if (!dir) {
@@ -153,19 +204,12 @@
         if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
             continue;
         }
-
-        int nameLength = strlen(name);
-        if (nameLength > pathRemaining) {
-            LOG(ERROR) << "path " << path << "/" << name << " too long";
-            continue;
-        }
-        strcpy(fileSpot, name);
-
+        pathStr.append(name);
         if (entry->d_type == DT_DIR) {
-            deleteRecursive(pathbuf);
-            rmdir(pathbuf);
+            deleteRecursive(pathStr.c_str());
+            rmdir(pathStr.c_str());
         } else {
-            unlink(pathbuf);
+            unlink(pathStr.c_str());
         }
     }
     closedir(dir);
diff --git a/media/mtp/MtpUtils.h b/media/mtp/MtpUtils.h
index a2bb7e1..b7c72f5 100644
--- a/media/mtp/MtpUtils.h
+++ b/media/mtp/MtpUtils.h
@@ -17,13 +17,21 @@
 #ifndef _MTP_UTILS_H
 #define _MTP_UTILS_H
 
+#include "private/android_filesystem_config.h"
+
 #include <stdint.h>
 
 namespace android {
 
+constexpr int FILE_GROUP = AID_MEDIA_RW;
+constexpr int FILE_PERM = 0664;
+constexpr int DIR_PERM = 0775;
+
 bool parseDateTime(const char* dateTime, time_t& outSeconds);
 void formatDateTime(time_t seconds, char* buffer, int bufferLength);
 
+int makeFolder(const char *path);
+int copyRecursive(const char *fromPath, const char *toPath);
 int copyFile(const char *fromPath, const char *toPath);
 void deleteRecursive(const char* path);
 void deletePath(const char* path);
diff --git a/media/mtp/OWNERS b/media/mtp/OWNERS
new file mode 100644
index 0000000..219307b
--- /dev/null
+++ b/media/mtp/OWNERS
@@ -0,0 +1 @@
+zhangjerry@google.com
diff --git a/media/mtp/tests/MtpFfsHandle_test.cpp b/media/mtp/tests/MtpFfsHandle_test.cpp
index 8d7301d..9c916b7 100644
--- a/media/mtp/tests/MtpFfsHandle_test.cpp
+++ b/media/mtp/tests/MtpFfsHandle_test.cpp
@@ -25,6 +25,7 @@
 #include <unistd.h>
 #include <utils/Log.h>
 
+#include "MtpDescriptors.h"
 #include "MtpFfsHandle.h"
 #include "MtpFfsCompatHandle.h"
 
@@ -66,8 +67,8 @@
         handle = std::make_unique<T>();
 
         EXPECT_EQ(pipe(fd), 0);
-        handle->mControl.reset(fd[0]);
-        control.reset(fd[1]);
+        control.reset(fd[0]);
+        handle->mControl.reset(fd[1]);
 
         EXPECT_EQ(pipe(fd), 0);
         EXPECT_EQ(fcntl(fd[0], F_SETPIPE_SZ, 1048576), 1048576);
@@ -83,7 +84,7 @@
         intr.reset(fd[0]);
         handle->mIntr.reset(fd[1]);
 
-        handle->start();
+        EXPECT_EQ(handle->start(), 0);
     }
 
     ~MtpFfsHandleTest() {
@@ -94,6 +95,16 @@
 typedef ::testing::Types<MtpFfsHandle, MtpFfsCompatHandle> mtpHandles;
 TYPED_TEST_CASE(MtpFfsHandleTest, mtpHandles);
 
+TYPED_TEST(MtpFfsHandleTest, testControl) {
+    EXPECT_TRUE(this->handle->writeDescriptors());
+    struct desc_v2 desc;
+    struct functionfs_strings strings;
+    EXPECT_EQ(read(this->control, &desc, sizeof(desc)), (long)sizeof(desc));
+    EXPECT_EQ(read(this->control, &strings, sizeof(strings)), (long)sizeof(strings));
+    EXPECT_TRUE(std::memcmp(&desc, &mtp_desc_v2, sizeof(desc)) == 0);
+    EXPECT_TRUE(std::memcmp(&strings, &mtp_strings, sizeof(strings)) == 0);
+}
+
 TYPED_TEST(MtpFfsHandleTest, testRead) {
     EXPECT_EQ(write(this->bulk_out, dummyDataStr.c_str(), TEST_PACKET_SIZE), TEST_PACKET_SIZE);
     char buf[TEST_PACKET_SIZE + 1];
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
index d1278a9..eed804a 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
@@ -19,6 +19,7 @@
 setpriority: 1
 sigaltstack: 1
 clone: 1
+sched_setscheduler: 1
 lseek: 1
 newfstatat: 1
 faccessat: 1
diff --git a/services/medialog/Android.bp b/services/medialog/Android.bp
new file mode 100644
index 0000000..1f811d3
--- /dev/null
+++ b/services/medialog/Android.bp
@@ -0,0 +1,21 @@
+cc_library_shared {
+    name: "libmedialogservice",
+
+    srcs: [
+        "IMediaLogService.cpp",
+        "MediaLogService.cpp",
+    ],
+
+    shared_libs: [
+        "libaudioutils",
+        "libbinder",
+        "liblog",
+        "libnbaio",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+}
diff --git a/services/medialog/Android.mk b/services/medialog/Android.mk
deleted file mode 100644
index 423b186..0000000
--- a/services/medialog/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := MediaLogService.cpp IMediaLogService.cpp
-
-LOCAL_SHARED_LIBRARIES := libbinder libutils liblog libnbaio libaudioutils
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_MODULE:= libmedialogservice
-
-LOCAL_C_INCLUDES := $(call include-path-for, audio-utils)
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/minijail/Android.mk b/services/minijail/Android.mk
index 6b35d91..67055a8 100644
--- a/services/minijail/Android.mk
+++ b/services/minijail/Android.mk
@@ -1,9 +1,12 @@
 LOCAL_PATH := $(call my-dir)
 
+minijail_common_cflags := -Wall -Werror
+
 # Small library for media.extractor and media.codec sandboxing.
 include $(CLEAR_VARS)
 LOCAL_MODULE := libavservices_minijail
 LOCAL_SRC_FILES := minijail.cpp
+LOCAL_CFLAGS := $(minijail_common_cflags)
 LOCAL_SHARED_LIBRARIES := libbase libminijail
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
 include $(BUILD_SHARED_LIBRARY)
@@ -13,6 +16,7 @@
 LOCAL_MODULE := libavservices_minijail_vendor
 LOCAL_VENDOR_MODULE := true
 LOCAL_SRC_FILES := minijail.cpp
+LOCAL_CFLAGS := $(minijail_common_cflags)
 LOCAL_SHARED_LIBRARIES := libbase libminijail
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
 include $(BUILD_SHARED_LIBRARY)
@@ -21,5 +25,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libavservices_minijail_unittest
 LOCAL_SRC_FILES := minijail.cpp av_services_minijail_unittest.cpp
+LOCAL_CFLAGS := $(minijail_common_cflags)
 LOCAL_SHARED_LIBRARIES := libbase libminijail
 include $(BUILD_NATIVE_TEST)