Merge "MediaExtractor: Fix use-after-free"
diff --git a/camera/camera2/CaptureRequest.cpp b/camera/camera2/CaptureRequest.cpp
index 983d29b..1843ec4 100644
--- a/camera/camera2/CaptureRequest.cpp
+++ b/camera/camera2/CaptureRequest.cpp
@@ -18,6 +18,7 @@
 // #define LOG_NDEBUG 0
 #define LOG_TAG "CameraRequest"
 #include <utils/Log.h>
+#include <utils/String16.h>
 
 #include <camera/camera2/CaptureRequest.h>
 
@@ -42,18 +43,39 @@
         return BAD_VALUE;
     }
 
-    mMetadata.clear();
     mSurfaceList.clear();
     mStreamIdxList.clear();
     mSurfaceIdxList.clear();
+    mPhysicalCameraSettings.clear();
 
     status_t err = OK;
 
-    if ((err = mMetadata.readFromParcel(parcel)) != OK) {
-        ALOGE("%s: Failed to read metadata from parcel", __FUNCTION__);
+    int32_t settingsCount;
+    if ((err = parcel->readInt32(&settingsCount)) != OK) {
+        ALOGE("%s: Failed to read the settings count from parcel: %d", __FUNCTION__, err);
         return err;
     }
-    ALOGV("%s: Read metadata from parcel", __FUNCTION__);
+
+    if (settingsCount <= 0) {
+        ALOGE("%s: Settings count %d should always be positive!", __FUNCTION__, settingsCount);
+        return BAD_VALUE;
+    }
+
+    for (int32_t i = 0; i < settingsCount; i++) {
+        String16 id;
+        if ((err = parcel->readString16(&id)) != OK) {
+            ALOGE("%s: Failed to read camera id!", __FUNCTION__);
+            return BAD_VALUE;
+        }
+
+        CameraMetadata settings;
+        if ((err = settings.readFromParcel(parcel)) != OK) {
+            ALOGE("%s: Failed to read metadata from parcel", __FUNCTION__);
+            return err;
+        }
+        ALOGV("%s: Read metadata from parcel", __FUNCTION__);
+        mPhysicalCameraSettings.push_back({std::string(String8(id).string()), settings});
+    }
 
     int isReprocess = 0;
     if ((err = parcel->readInt32(&isReprocess)) != OK) {
@@ -135,10 +157,25 @@
 
     status_t err = OK;
 
-    if ((err = mMetadata.writeToParcel(parcel)) != OK) {
+    int32_t settingsCount = static_cast<int32_t>(mPhysicalCameraSettings.size());
+
+    if ((err = parcel->writeInt32(settingsCount)) != OK) {
+        ALOGE("%s: Failed to write settings count!", __FUNCTION__);
         return err;
     }
 
+    for (const auto &it : mPhysicalCameraSettings) {
+        if ((err = parcel->writeString16(String16(it.id.c_str()))) != OK) {
+            ALOGE("%s: Failed to camera id!", __FUNCTION__);
+            return err;
+        }
+
+        if ((err = it.settings.writeToParcel(parcel)) != OK) {
+            ALOGE("%s: Failed to write settings!", __FUNCTION__);
+            return err;
+        }
+    }
+
     parcel->writeInt32(mIsReprocess ? 1 : 0);
 
     if (mSurfaceConverted) {
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 813d6c9..feb04c2 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -1,6 +1,6 @@
 /*
 **
-** Copyright 2015, The Android Open Source Project
+** Copyright 2015-2018, 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.
@@ -64,6 +64,10 @@
     return mIsShared;
 }
 
+String16 OutputConfiguration::getPhysicalCameraId() const {
+    return mPhysicalCameraId;
+}
+
 OutputConfiguration::OutputConfiguration() :
         mRotation(INVALID_ROTATION),
         mSurfaceSetID(INVALID_SET_ID),
@@ -139,6 +143,8 @@
         return err;
     }
 
+    parcel->readString16(&mPhysicalCameraId);
+
     mRotation = rotation;
     mSurfaceSetID = setID;
     mSurfaceType = surfaceType;
@@ -153,8 +159,9 @@
         mGbps.push_back(surface.graphicBufferProducer);
     }
 
-    ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d",
-            __FUNCTION__, mRotation, mSurfaceSetID, mSurfaceType);
+    ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d,"
+          " physicalCameraId = %s", __FUNCTION__, mRotation, mSurfaceSetID,
+          mSurfaceType, String8(mPhysicalCameraId).string());
 
     return err;
 }
@@ -204,6 +211,9 @@
     err = parcel->writeParcelableVector(surfaceShims);
     if (err != OK) return err;
 
+    err = parcel->writeString16(mPhysicalCameraId);
+    if (err != OK) return err;
+
     return OK;
 }
 
diff --git a/camera/include/camera/camera2/CaptureRequest.h b/camera/include/camera/camera2/CaptureRequest.h
index c53799f..506abab 100644
--- a/camera/include/camera/camera2/CaptureRequest.h
+++ b/camera/include/camera/camera2/CaptureRequest.h
@@ -40,7 +40,11 @@
     CaptureRequest(CaptureRequest&& rhs) noexcept;
     virtual ~CaptureRequest();
 
-    CameraMetadata          mMetadata;
+    struct PhysicalCameraSettings {
+        std::string id;
+        CameraMetadata settings;
+    };
+    std::vector<PhysicalCameraSettings> mPhysicalCameraSettings;
 
     // Used by NDK client to pass surfaces by stream/surface index.
     bool                    mSurfaceConverted = false;
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 3599604..a80f44b 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2015-2018 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.
@@ -46,6 +46,7 @@
     int                        getHeight() const;
     bool                       isDeferred() const;
     bool                       isShared() const;
+    String16                   getPhysicalCameraId() const;
     /**
      * Keep impl up-to-date with OutputConfiguration.java in frameworks/base
      */
@@ -74,7 +75,8 @@
                 mHeight == other.mHeight &&
                 mIsDeferred == other.mIsDeferred &&
                 mIsShared == other.mIsShared &&
-                gbpsEqual(other));
+                gbpsEqual(other) &&
+                mPhysicalCameraId == other.mPhysicalCameraId );
     }
     bool operator != (const OutputConfiguration& other) const {
         return !(*this == other);
@@ -102,6 +104,9 @@
         if (mIsShared != other.mIsShared) {
             return mIsShared < other.mIsShared;
         }
+        if (mPhysicalCameraId != other.mPhysicalCameraId) {
+            return mPhysicalCameraId < other.mPhysicalCameraId;
+        }
         return gbpsLessThan(other);
     }
     bool operator > (const OutputConfiguration& other) const {
@@ -120,8 +125,7 @@
     int                        mHeight;
     bool                       mIsDeferred;
     bool                       mIsShared;
-    // helper function
-    static String16 readMaybeEmptyString16(const android::Parcel* parcel);
+    String16                   mPhysicalCameraId;
 };
 } // namespace params
 } // namespace camera2
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index f7cea4f..ef1c61f 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -372,7 +372,8 @@
         const ACaptureRequest* request, /*out*/sp<CaptureRequest>& outReq) {
     camera_status_t ret;
     sp<CaptureRequest> req(new CaptureRequest());
-    req->mMetadata = request->settings->getInternalData();
+    req->mPhysicalCameraSettings.push_back({std::string(mCameraId.string()),
+            request->settings->getInternalData()});
     req->mIsReprocess = false; // NDK does not support reprocessing yet
     req->mContext = request->context;
     req->mSurfaceConverted = true; // set to true, and fill in stream/surface idx to speed up IPC
@@ -418,7 +419,7 @@
 ACaptureRequest*
 CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req) {
     ACaptureRequest* pRequest = new ACaptureRequest();
-    CameraMetadata clone = req->mMetadata;
+    CameraMetadata clone = req->mPhysicalCameraSettings.begin()->settings;
     pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST);
     pRequest->targets  = new ACameraOutputTargets();
     for (size_t i = 0; i < req->mSurfaceList.size(); i++) {
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 29ad09b..62b0ec9 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -305,6 +305,7 @@
         case ACAMERA_STATISTICS_FACE_DETECT_MODE:
         case ACAMERA_STATISTICS_HOT_PIXEL_MAP_MODE:
         case ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE:
+        case ACAMERA_STATISTICS_OIS_DATA_MODE:
         case ACAMERA_TONEMAP_CURVE_BLUE:
         case ACAMERA_TONEMAP_CURVE_GREEN:
         case ACAMERA_TONEMAP_CURVE_RED:
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 6e861a6..ffb2900 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -69,6 +69,7 @@
     ACAMERA_SYNC,
     ACAMERA_REPROCESS,
     ACAMERA_DEPTH,
+    ACAMERA_LOGICAL_MULTI_CAMERA,
     ACAMERA_SECTION_COUNT,
 
     ACAMERA_VENDOR = 0x8000
@@ -104,6 +105,9 @@
     ACAMERA_SYNC_START             = ACAMERA_SYNC              << 16,
     ACAMERA_REPROCESS_START        = ACAMERA_REPROCESS         << 16,
     ACAMERA_DEPTH_START            = ACAMERA_DEPTH             << 16,
+    ACAMERA_LOGICAL_MULTI_CAMERA_START
+                                   = ACAMERA_LOGICAL_MULTI_CAMERA
+                                                                << 16,
     ACAMERA_VENDOR_START           = ACAMERA_VENDOR            << 16
 } acamera_metadata_section_start_t;
 
@@ -4562,6 +4566,85 @@
      */
     ACAMERA_STATISTICS_LENS_SHADING_MAP_MODE =                  // byte (acamera_metadata_enum_android_statistics_lens_shading_map_mode_t)
             ACAMERA_STATISTICS_START + 16,
+    /**
+     * <p>Whether the camera device outputs the OIS data in output
+     * result metadata.</p>
+     *
+     * <p>Type: byte (acamera_metadata_enum_android_statistics_ois_data_mode_t)</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+     *   <li>ACaptureRequest</li>
+     * </ul></p>
+     *
+     * <p>When set to ON,
+     * ACAMERA_STATISTICS_OIS_TIMESTAMPS, android.statistics.oisShiftPixelX,
+     * android.statistics.oisShiftPixelY will provide OIS data in the output result metadata.</p>
+     *
+     * @see ACAMERA_STATISTICS_OIS_TIMESTAMPS
+     */
+    ACAMERA_STATISTICS_OIS_DATA_MODE =                          // byte (acamera_metadata_enum_android_statistics_ois_data_mode_t)
+            ACAMERA_STATISTICS_START + 17,
+    /**
+     * <p>An array of timestamps of OIS samples, in nanoseconds.</p>
+     *
+     * <p>Type: int64[n]</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+     * </ul></p>
+     *
+     * <p>The array contains the timestamps of OIS samples. The timestamps are in the same
+     * timebase as and comparable to ACAMERA_SENSOR_TIMESTAMP.</p>
+     *
+     * @see ACAMERA_SENSOR_TIMESTAMP
+     */
+    ACAMERA_STATISTICS_OIS_TIMESTAMPS =                         // int64[n]
+            ACAMERA_STATISTICS_START + 18,
+    /**
+     * <p>An array of shifts of OIS samples, in x direction.</p>
+     *
+     * <p>Type: float[n]</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+     * </ul></p>
+     *
+     * <p>The array contains the amount of shifts in x direction, in pixels, based on OIS samples.
+     * A positive value is a shift from left to right in active array coordinate system. For
+     * example, if the optical center is (1000, 500) in active array coordinates, an shift of
+     * (3, 0) puts the new optical center at (1003, 500).</p>
+     * <p>The number of shifts must match the number of timestamps in
+     * ACAMERA_STATISTICS_OIS_TIMESTAMPS.</p>
+     *
+     * @see ACAMERA_STATISTICS_OIS_TIMESTAMPS
+     */
+    ACAMERA_STATISTICS_OIS_X_SHIFTS =                           // float[n]
+            ACAMERA_STATISTICS_START + 19,
+    /**
+     * <p>An array of shifts of OIS samples, in y direction.</p>
+     *
+     * <p>Type: float[n]</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+     * </ul></p>
+     *
+     * <p>The array contains the amount of shifts in y direction, in pixels, based on OIS samples.
+     * A positive value is a shift from top to bottom in active array coordinate system. For
+     * example, if the optical center is (1000, 500) in active array coordinates, an shift of
+     * (0, 5) puts the new optical center at (1000, 505).</p>
+     * <p>The number of shifts must match the number of timestamps in
+     * ACAMERA_STATISTICS_OIS_TIMESTAMPS.</p>
+     *
+     * @see ACAMERA_STATISTICS_OIS_TIMESTAMPS
+     */
+    ACAMERA_STATISTICS_OIS_Y_SHIFTS =                           // float[n]
+            ACAMERA_STATISTICS_START + 20,
     ACAMERA_STATISTICS_END,
 
     /**
@@ -4634,6 +4717,24 @@
      */
     ACAMERA_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES =  // byte[n]
             ACAMERA_STATISTICS_INFO_START + 7,
+    /**
+     * <p>List of OIS data output modes for ACAMERA_STATISTICS_OIS_DATA_MODE that
+     * are supported by this camera device.</p>
+     *
+     * @see ACAMERA_STATISTICS_OIS_DATA_MODE
+     *
+     * <p>Type: byte[n]</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+     * </ul></p>
+     *
+     * <p>If no OIS data output is available for this camera device, this key will
+     * contain only OFF.</p>
+     */
+    ACAMERA_STATISTICS_INFO_AVAILABLE_OIS_DATA_MODES =          // byte[n]
+            ACAMERA_STATISTICS_INFO_START + 8,
     ACAMERA_STATISTICS_INFO_END,
 
     /**
@@ -5165,6 +5266,29 @@
             ACAMERA_DEPTH_START + 4,
     ACAMERA_DEPTH_END,
 
+    /**
+     * <p>The accuracy of frame timestamp synchronization between physical cameras</p>
+     *
+     * <p>Type: byte (acamera_metadata_enum_android_logical_multi_camera_sensor_sync_type_t)</p>
+     *
+     * <p>This tag may appear in:
+     * <ul>
+     *   <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+     * </ul></p>
+     *
+     * <p>The accuracy of the frame timestamp synchronization determines the physical cameras'
+     * ability to start exposure at the same time. If the sensorSyncType is CALIBRATED,
+     * the physical camera sensors usually run in master-slave mode so that their shutter
+     * time is synchronized. For APPROXIMATE sensorSyncType, the camera sensors usually run in
+     * master-master mode, and there could be offset between their start of exposure.</p>
+     * <p>In both cases, all images generated for a particular capture request still carry the same
+     * timestamps, so that they can be used to look up the matching frame number and
+     * onCaptureStarted callback.</p>
+     */
+    ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE =             // byte (acamera_metadata_enum_android_logical_multi_camera_sensor_sync_type_t)
+            ACAMERA_LOGICAL_MULTI_CAMERA_START + 1,
+    ACAMERA_LOGICAL_MULTI_CAMERA_END,
+
 } acamera_metadata_tag_t;
 
 /**
@@ -6895,6 +7019,52 @@
      */
     ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING           = 10,
 
+    /**
+     * <p>The camera device is a logical camera backed by two or more physical cameras that are
+     * also exposed to the application.</p>
+     * <p>This capability requires the camera device to support the following:</p>
+     * <ul>
+     * <li>This camera device must list the following static metadata entries in <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html">CameraCharacteristics</a>:<ul>
+     * <li>android.logicalMultiCamera.physicalIds</li>
+     * <li>ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE</li>
+     * </ul>
+     * </li>
+     * <li>The underlying physical cameras' static metadata must list the following entries,
+     *   so that the application can correlate pixels from the physical streams:<ul>
+     * <li>ACAMERA_LENS_POSE_REFERENCE</li>
+     * <li>ACAMERA_LENS_POSE_ROTATION</li>
+     * <li>ACAMERA_LENS_POSE_TRANSLATION</li>
+     * <li>ACAMERA_LENS_INTRINSIC_CALIBRATION</li>
+     * <li>ACAMERA_LENS_RADIAL_DISTORTION</li>
+     * </ul>
+     * </li>
+     * <li>The logical camera device must be LIMITED or higher device.</li>
+     * </ul>
+     * <p>Both the logical camera device and its underlying physical devices support the
+     * mandatory stream combinations required for their device levels.</p>
+     * <p>Additionally, for each guaranteed stream combination, the logical camera supports:</p>
+     * <ul>
+     * <li>Replacing one logical {@link AIMAGE_FORMAT_YUV_420_888 YUV_420_888}
+     *   or raw stream with two physical streams of the same size and format, each from a
+     *   separate physical camera, given that the size and format are supported by both
+     *   physical cameras.</li>
+     * <li>Adding two raw streams, each from one physical camera, if the logical camera doesn't
+     *   advertise RAW capability, but the underlying physical cameras do. This is usually
+     *   the case when the physical cameras have different sensor sizes.</li>
+     * </ul>
+     * <p>Using physical streams in place of a logical stream of the same size and format will
+     * not slow down the frame rate of the capture, as long as the minimum frame duration
+     * of the physical and logical streams are the same.</p>
+     *
+     * @see ACAMERA_LENS_INTRINSIC_CALIBRATION
+     * @see ACAMERA_LENS_POSE_REFERENCE
+     * @see ACAMERA_LENS_POSE_ROTATION
+     * @see ACAMERA_LENS_POSE_TRANSLATION
+     * @see ACAMERA_LENS_RADIAL_DISTORTION
+     * @see ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
+     */
+    ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA      = 11,
+
 } acamera_metadata_enum_android_request_available_capabilities_t;
 
 
@@ -7226,6 +7396,20 @@
 
 } acamera_metadata_enum_android_statistics_lens_shading_map_mode_t;
 
+// ACAMERA_STATISTICS_OIS_DATA_MODE
+typedef enum acamera_metadata_enum_acamera_statistics_ois_data_mode {
+    /**
+     * <p>Do not include OIS data in the capture result.</p>
+     */
+    ACAMERA_STATISTICS_OIS_DATA_MODE_OFF                             = 0,
+
+    /**
+     * <p>Include OIS data in the capture result.</p>
+     */
+    ACAMERA_STATISTICS_OIS_DATA_MODE_ON                              = 1,
+
+} acamera_metadata_enum_android_statistics_ois_data_mode_t;
+
 
 
 // ACAMERA_TONEMAP_MODE
@@ -7387,6 +7571,37 @@
      */
     ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_3                          = 3,
 
+    /**
+     * <p>This camera device is backed by an external camera connected to this Android device.</p>
+     * <p>The device has capability identical to a LIMITED level device, with the following
+     * exceptions:</p>
+     * <ul>
+     * <li>The device may not report lens/sensor related information such as<ul>
+     * <li>ACAMERA_LENS_FOCAL_LENGTH</li>
+     * <li>ACAMERA_LENS_INFO_HYPERFOCAL_DISTANCE</li>
+     * <li>ACAMERA_SENSOR_INFO_PHYSICAL_SIZE</li>
+     * <li>ACAMERA_SENSOR_INFO_WHITE_LEVEL</li>
+     * <li>ACAMERA_SENSOR_BLACK_LEVEL_PATTERN</li>
+     * <li>ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT</li>
+     * <li>ACAMERA_SENSOR_ROLLING_SHUTTER_SKEW</li>
+     * </ul>
+     * </li>
+     * <li>The device will report 0 for ACAMERA_SENSOR_ORIENTATION</li>
+     * <li>The device has less guarantee on stable framerate, as the framerate partly depends
+     *   on the external camera being used.</li>
+     * </ul>
+     *
+     * @see ACAMERA_LENS_FOCAL_LENGTH
+     * @see ACAMERA_LENS_INFO_HYPERFOCAL_DISTANCE
+     * @see ACAMERA_SENSOR_BLACK_LEVEL_PATTERN
+     * @see ACAMERA_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+     * @see ACAMERA_SENSOR_INFO_PHYSICAL_SIZE
+     * @see ACAMERA_SENSOR_INFO_WHITE_LEVEL
+     * @see ACAMERA_SENSOR_ORIENTATION
+     * @see ACAMERA_SENSOR_ROLLING_SHUTTER_SKEW
+     */
+    ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL                   = 4,
+
 } acamera_metadata_enum_android_info_supported_hardware_level_t;
 
 
@@ -7474,6 +7689,25 @@
 } acamera_metadata_enum_android_depth_depth_is_exclusive_t;
 
 
+// ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE
+typedef enum acamera_metadata_enum_acamera_logical_multi_camera_sensor_sync_type {
+    /**
+     * <p>A software mechanism is used to synchronize between the physical cameras. As a result,
+     * the timestamp of an image from a physical stream is only an approximation of the
+     * image sensor start-of-exposure time.</p>
+     */
+    ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE        = 0,
+
+    /**
+     * <p>The camera device supports frame timestamp synchronization at the hardware level,
+     * and the timestamp of a physical stream image accurately reflects its
+     * start-of-exposure time.</p>
+     */
+    ACAMERA_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED         = 1,
+
+} acamera_metadata_enum_android_logical_multi_camera_sensor_sync_type_t;
+
+
 #endif /* __ANDROID_API__ >= 24 */
 
 __END_DECLS
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 8fe9a86..24c0c51 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -317,6 +317,9 @@
     EXPECT_TRUE(res.isOk()) << res;
 
     EXPECT_EQ(numCameras, static_cast<const int>(statuses.size()));
+    for (const auto &it : statuses) {
+        listener->onStatusChanged(it.status, String16(it.cameraId));
+    }
 
     for (int32_t i = 0; i < numCameras; i++) {
         String16 cameraId = String16(String8::format("%d", i));
@@ -421,6 +424,9 @@
         serviceListener = new TestCameraServiceListener();
         std::vector<hardware::CameraStatus> statuses;
         service->addListener(serviceListener, &statuses);
+        for (const auto &it : statuses) {
+            serviceListener->onStatusChanged(it.status, String16(it.cameraId));
+        }
         service->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE,
                 &numCameras);
     }
@@ -439,8 +445,9 @@
     ASSERT_NOT_NULL(service);
     EXPECT_TRUE(serviceListener->waitForNumCameras(numCameras));
     for (int32_t i = 0; i < numCameras; i++) {
+        String8 cameraId8 = String8::format("%d", i);
         // Make sure we're available, or skip device tests otherwise
-        String16 cameraId(String8::format("%d",i));
+        String16 cameraId(cameraId8);
         int32_t s = serviceListener->getStatus(cameraId);
         EXPECT_EQ(hardware::ICameraServiceListener::STATUS_PRESENT, s);
         if (s != hardware::ICameraServiceListener::STATUS_PRESENT) {
@@ -488,7 +495,7 @@
         EXPECT_TRUE(res.isOk()) << res;
 
         hardware::camera2::CaptureRequest request;
-        request.mMetadata = requestTemplate;
+        request.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate});
         request.mSurfaceList.add(surface);
         request.mIsReprocess = false;
         int64_t lastFrameNumber = 0;
@@ -515,7 +522,7 @@
                 /*out*/&requestTemplate);
         EXPECT_TRUE(res.isOk()) << res;
         hardware::camera2::CaptureRequest request2;
-        request2.mMetadata = requestTemplate;
+        request2.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate});
         request2.mSurfaceList.add(surface);
         request2.mIsReprocess = false;
         callbacks->clearStatus();
@@ -548,10 +555,10 @@
         EXPECT_TRUE(res.isOk()) << res;
         android::hardware::camera2::CaptureRequest request3;
         android::hardware::camera2::CaptureRequest request4;
-        request3.mMetadata = requestTemplate;
+        request3.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate});
         request3.mSurfaceList.add(surface);
         request3.mIsReprocess = false;
-        request4.mMetadata = requestTemplate2;
+        request4.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate2});
         request4.mSurfaceList.add(surface);
         request4.mIsReprocess = false;
         std::vector<hardware::camera2::CaptureRequest> requestList;
@@ -585,3 +592,62 @@
     }
 
 };
+
+TEST_F(CameraClientBinderTest, CheckBinderCaptureRequest) {
+    sp<CaptureRequest> requestOriginal, requestParceled;
+    sp<IGraphicBufferProducer> gbProducer;
+    sp<IGraphicBufferConsumer> gbConsumer;
+    BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
+    sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
+    Vector<sp<Surface>> surfaceList;
+    surfaceList.push_back(surface);
+    std::string physicalDeviceId1 = "0";
+    std::string physicalDeviceId2 = "1";
+    CameraMetadata physicalDeviceSettings1, physicalDeviceSettings2;
+    uint8_t intent1 = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
+    uint8_t intent2 = ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
+    EXPECT_EQ(OK, physicalDeviceSettings1.update(ANDROID_CONTROL_CAPTURE_INTENT, &intent1, 1));
+    EXPECT_EQ(OK, physicalDeviceSettings2.update(ANDROID_CONTROL_CAPTURE_INTENT, &intent2, 1));
+
+    requestParceled = new CaptureRequest();
+    Parcel p;
+    EXPECT_TRUE(requestParceled->readFromParcel(&p) != OK);
+    p.writeInt32(0);
+    p.setDataPosition(0);
+    EXPECT_TRUE(requestParceled->readFromParcel(&p) != OK);
+    p.freeData();
+    p.writeInt32(-1);
+    p.setDataPosition(0);
+    EXPECT_TRUE(requestParceled->readFromParcel(&p) != OK);
+    p.freeData();
+    p.writeInt32(1);
+    p.setDataPosition(0);
+    EXPECT_TRUE(requestParceled->readFromParcel(&p) != OK);
+
+    requestOriginal = new CaptureRequest();
+    requestOriginal->mPhysicalCameraSettings.push_back({physicalDeviceId1,
+            physicalDeviceSettings1});
+    requestOriginal->mPhysicalCameraSettings.push_back({physicalDeviceId2,
+            physicalDeviceSettings2});
+    requestOriginal->mSurfaceList.push_back(surface);
+    requestOriginal->mIsReprocess = false;
+    requestOriginal->mSurfaceConverted = false;
+
+    p.freeData();
+    EXPECT_TRUE(requestOriginal->writeToParcel(&p) == OK);
+    p.setDataPosition(0);
+    EXPECT_TRUE(requestParceled->readFromParcel(&p) == OK);
+    EXPECT_EQ(requestParceled->mIsReprocess, false);
+    EXPECT_FALSE(requestParceled->mSurfaceList.empty());
+    EXPECT_EQ(2u, requestParceled->mPhysicalCameraSettings.size());
+    auto it = requestParceled->mPhysicalCameraSettings.begin();
+    EXPECT_EQ(physicalDeviceId1, it->id);
+    EXPECT_TRUE(it->settings.exists(ANDROID_CONTROL_CAPTURE_INTENT));
+    auto entry = it->settings.find(ANDROID_CONTROL_CAPTURE_INTENT);
+    EXPECT_EQ(entry.data.u8[0], intent1);
+    it++;
+    EXPECT_EQ(physicalDeviceId2, it->id);
+    EXPECT_TRUE(it->settings.exists(ANDROID_CONTROL_CAPTURE_INTENT));
+    entry = it->settings.find(ANDROID_CONTROL_CAPTURE_INTENT);
+    EXPECT_EQ(entry.data.u8[0], intent2);
+};
diff --git a/camera/tests/VendorTagDescriptorTests.cpp b/camera/tests/VendorTagDescriptorTests.cpp
index 75cfb73..0ee358d 100644
--- a/camera/tests/VendorTagDescriptorTests.cpp
+++ b/camera/tests/VendorTagDescriptorTests.cpp
@@ -142,6 +142,7 @@
     EXPECT_EQ(OK, vDescOriginal->writeToParcel(&p));
     p.setDataPosition(0);
 
+    vDescParceled = new VendorTagDescriptor();
     ASSERT_EQ(OK, vDescParceled->readFromParcel(&p));
 
     // Ensure consistent tag count
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index 67017eb..5500d24 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+#define LOG_NDEBUG 0
+#define LOG_TAG "audioloop"
+#include <utils/Log.h>
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -37,11 +41,13 @@
 
 static void usage(const char* name)
 {
-    fprintf(stderr, "Usage: %s [-d du.ration] [-m] [-w] [<output-file>]\n", name);
+    fprintf(stderr, "Usage: %s [-d du.ration] [-m] [-w] [-N name] [<output-file>]\n", name);
     fprintf(stderr, "Encodes either a sine wave or microphone input to AMR format\n");
     fprintf(stderr, "    -d    duration in seconds, default 5 seconds\n");
     fprintf(stderr, "    -m    use microphone for input, default sine source\n");
     fprintf(stderr, "    -w    use AMR wideband (default narrowband)\n");
+    fprintf(stderr, "    -N    name of the encoder; must be set with -M\n");
+    fprintf(stderr, "    -M    media type of the encoder; must be set with -N\n");
     fprintf(stderr, "    <output-file> output file for AMR encoding,"
             " if unspecified, decode to speaker.\n");
 }
@@ -54,8 +60,10 @@
     bool outputWBAMR = false;
     bool playToSpeaker = true;
     const char* fileOut = NULL;
+    AString name;
+    AString mediaType;
     int ch;
-    while ((ch = getopt(argc, argv, "d:mw")) != -1) {
+    while ((ch = getopt(argc, argv, "d:mwN:M:")) != -1) {
         switch (ch) {
         case 'd':
             duration = atoi(optarg);
@@ -66,6 +74,12 @@
         case 'w':
             outputWBAMR = true;
             break;
+        case 'N':
+            name.setTo(optarg);
+            break;
+        case 'M':
+            mediaType.setTo(optarg);
+            break;
         default:
             usage(argv[0]);
             return -1;
@@ -76,8 +90,18 @@
     if (argc == 1) {
         fileOut = argv[0];
     }
-    const int32_t kSampleRate = outputWBAMR ? 16000 : 8000;
-    const int32_t kBitRate = outputWBAMR ? 16000 : 8000;
+    if ((name.empty() && !mediaType.empty()) || (!name.empty() && mediaType.empty())) {
+        fprintf(stderr, "-N and -M must be set together\n");
+        usage(argv[0]);
+        return -1;
+    }
+    if (!name.empty() && fileOut != NULL) {
+        fprintf(stderr, "-N and -M cannot be used with <output file>\n");
+        usage(argv[0]);
+        return -1;
+    }
+    int32_t sampleRate = !name.empty() ? 44100 : outputWBAMR ? 16000 : 8000;
+    int32_t bitRate = sampleRate;
 
     android::ProcessState::self()->startThreadPool();
     sp<MediaSource> source;
@@ -87,22 +111,27 @@
         source = new AudioSource(
                 AUDIO_SOURCE_MIC,
                 String16(),
-                kSampleRate,
+                sampleRate,
                 channels);
     } else {
         // use a sine source at 500 hz.
-        source = new SineSource(kSampleRate, channels);
+        source = new SineSource(sampleRate, channels);
     }
 
     sp<AMessage> meta = new AMessage;
-    meta->setString(
-            "mime",
-            outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
-                    : MEDIA_MIMETYPE_AUDIO_AMR_NB);
+    if (name.empty()) {
+        meta->setString(
+                "mime",
+                outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
+                        : MEDIA_MIMETYPE_AUDIO_AMR_NB);
+    } else {
+        meta->setString("mime", mediaType);
+        meta->setString("testing-name", name);
+    }
 
     meta->setInt32("channel-count", channels);
-    meta->setInt32("sample-rate", kSampleRate);
-    meta->setInt32("bitrate", kBitRate);
+    meta->setInt32("sample-rate", sampleRate);
+    meta->setInt32("bitrate", bitRate);
     int32_t maxInputSize;
     if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) {
         meta->setInt32("max-input-size", maxInputSize);
@@ -131,13 +160,14 @@
         sp<MediaSource> decoder = SimpleDecodingSource::Create(encoder);
 
         if (playToSpeaker) {
-            AudioPlayer *player = new AudioPlayer(NULL);
-            player->setSource(decoder);
-            player->start();
+            AudioPlayer player(NULL);
+            player.setSource(decoder);
+            player.start();
             sleep(duration);
 
+ALOGI("Line: %d", __LINE__);
             decoder.clear(); // must clear |decoder| otherwise delete player will hang.
-            delete player; // there is no player->stop()...
+ALOGI("Line: %d", __LINE__);
         } else {
             CHECK_EQ(decoder->start(), (status_t)OK);
             MediaBuffer* buffer;
@@ -151,6 +181,7 @@
             }
             CHECK_EQ(decoder->stop(), (status_t)OK);
         }
+ALOGI("Line: %d", __LINE__);
     }
 
     return 0;
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 5da8114..e40a6cd 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -510,7 +510,9 @@
  * This could, for example, affect which microphones are used and how the
  * recorded data is processed.
  *
- * The default, if you do not call this function, is AAUDIO_INPUT_PRESET_GENERIC.
+ * The default, if you do not call this function, is AAUDIO_INPUT_PRESET_VOICE_RECOGNITION.
+ * That is because VOICE_RECOGNITION is the preset with the lowest latency
+ * on many platforms.
  *
  * @param builder reference provided by AAudio_createStreamBuilder()
  * @param inputPreset the desired configuration for recording
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 82c0667..9a2405a 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -93,7 +93,7 @@
     }
     mInputPreset = builder.getInputPreset();
     if (mInputPreset == AAUDIO_UNSPECIFIED) {
-        mInputPreset = AAUDIO_INPUT_PRESET_GENERIC;
+        mInputPreset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
     }
 
     // callbacks
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 42b585f..c59ee6c 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -515,9 +515,9 @@
     aaudio_stream_state_t       mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
     aaudio_performance_mode_t   mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
 
-    aaudio_usage_t              mUsage           = AAUDIO_USAGE_MEDIA;
-    aaudio_content_type_t       mContentType     = AAUDIO_CONTENT_TYPE_MUSIC;
-    aaudio_input_preset_t       mInputPreset     = AAUDIO_INPUT_PRESET_GENERIC;
+    aaudio_usage_t              mUsage           = AAUDIO_UNSPECIFIED;
+    aaudio_content_type_t       mContentType     = AAUDIO_UNSPECIFIED;
+    aaudio_input_preset_t       mInputPreset     = AAUDIO_UNSPECIFIED;
 
     int32_t                     mSessionId = AAUDIO_UNSPECIFIED;
 
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index c5dfb7c..3352b33 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -86,10 +86,15 @@
             // AudioRecord::Buffer
             // TODO define our own AudioBuffer and pass it from the subclasses.
             AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
-            if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED || !mCallbackEnabled.load()) {
+            if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
+                ALOGW("processCallbackCommon() data, stream disconnected");
+                audioBuffer->size = SIZE_STOP_CALLBACKS;
+            } else if (!mCallbackEnabled.load()) {
+                ALOGW("processCallbackCommon() stopping because callback disabled");
                 audioBuffer->size = SIZE_STOP_CALLBACKS;
             } else {
                 if (audioBuffer->frameCount == 0) {
+                    ALOGW("processCallbackCommon() data, frameCount is zero");
                     return;
                 }
 
@@ -106,7 +111,7 @@
                 if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
                     audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
                 } else { // STOP or invalid result
-                    ALOGW("%s() stop stream by faking an error", __func__);
+                    ALOGW("%s() callback requested stop, fake an error", __func__);
                     audioBuffer->size = SIZE_STOP_CALLBACKS;
                     // Disable the callback just in case AudioFlinger keeps trying to call us.
                     mCallbackEnabled.store(false);
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index 6a506b3..494edbc 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -121,9 +121,6 @@
 
     void forceDisconnect(bool errorCallbackEnabled = true);
 
-    void onStart() { mCallbackEnabled.store(true); }
-    void onStop() { mCallbackEnabled.store(false); }
-
     int64_t incrementFramesWritten(int32_t frames) {
         return mFramesWritten.increment(frames);
     }
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 61a0f8a..f7ae7d7 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -244,11 +244,13 @@
         return AAudioConvert_androidToAAudioResult(err);
     }
 
+    // Enable callback before starting AudioTrack to avoid shutting
+    // down because of a race condition.
+    mCallbackEnabled.store(true);
     err = mAudioRecord->start();
     if (err != OK) {
         return AAudioConvert_androidToAAudioResult(err);
     } else {
-        onStart();
         setState(AAUDIO_STREAM_STATE_STARTING);
     }
     return AAUDIO_OK;
@@ -258,11 +260,11 @@
     if (mAudioRecord.get() == nullptr) {
         return AAUDIO_ERROR_INVALID_STATE;
     }
-    onStop();
     setState(AAUDIO_STREAM_STATE_STOPPING);
     incrementFramesWritten(getFramesRead() - getFramesWritten()); // TODO review
     mTimestampPosition.set(getFramesRead());
     mAudioRecord->stop();
+    mCallbackEnabled.store(false);
     mFramesRead.reset32();
     mTimestampPosition.reset32();
     // Pass false to prevent errorCallback from being called after disconnect
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 52c7822..4d1b187 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -271,11 +271,13 @@
         return AAudioConvert_androidToAAudioResult(err);
     }
 
+    // Enable callback before starting AudioTrack to avoid shutting
+    // down because of a race condition.
+    mCallbackEnabled.store(true);
     err = mAudioTrack->start();
     if (err != OK) {
         return AAudioConvert_androidToAAudioResult(err);
     } else {
-        onStart();
         setState(AAUDIO_STREAM_STATE_STARTING);
     }
     return AAUDIO_OK;
@@ -292,9 +294,9 @@
               AAudio_convertStreamStateToText(getState()));
         return AAUDIO_ERROR_INVALID_STATE;
     }
-    onStop();
     setState(AAUDIO_STREAM_STATE_PAUSING);
     mAudioTrack->pause();
+    mCallbackEnabled.store(false);
     status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
     if (err != OK) {
         return AAudioConvert_androidToAAudioResult(err);
@@ -323,13 +325,13 @@
         ALOGE("requestStop() no AudioTrack");
         return AAUDIO_ERROR_INVALID_STATE;
     }
-    onStop();
     setState(AAUDIO_STREAM_STATE_STOPPING);
     incrementFramesRead(getFramesWritten() - getFramesRead()); // TODO review
     mTimestampPosition.set(getFramesWritten());
     mFramesWritten.reset32();
     mTimestampPosition.reset32();
     mAudioTrack->stop();
+    mCallbackEnabled.store(false);
     return checkForDisconnectRequest(false);;
 }
 
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 2bee6e3..2a34016 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -341,7 +341,7 @@
     STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
     STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
     if (preset == AAUDIO_UNSPECIFIED) {
-        preset = AAUDIO_INPUT_PRESET_GENERIC;
+        preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
     }
     return (audio_source_t) preset; // same value
 }
diff --git a/media/libaaudio/tests/test_attributes.cpp b/media/libaaudio/tests/test_attributes.cpp
index 9cbf113..b01af25 100644
--- a/media/libaaudio/tests/test_attributes.cpp
+++ b/media/libaaudio/tests/test_attributes.cpp
@@ -76,7 +76,7 @@
 
     aaudio_input_preset_t expectedPreset =
             (preset == DONT_SET || preset == AAUDIO_UNSPECIFIED)
-            ? AAUDIO_INPUT_PRESET_GENERIC // default
+            ? AAUDIO_INPUT_PRESET_VOICE_RECOGNITION // default
             : preset;
     EXPECT_EQ(expectedPreset, AAudioStream_getInputPreset(aaudioStream));
 
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 16150f6..7969ed0 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -858,6 +858,7 @@
                                         audio_io_handle_t *output,
                                         audio_session_t session,
                                         audio_stream_type_t *stream,
+                                        pid_t pid,
                                         uid_t uid,
                                         const audio_config_t *config,
                                         audio_output_flags_t flags,
@@ -866,7 +867,7 @@
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return NO_INIT;
-    return aps->getOutputForAttr(attr, output, session, stream, uid,
+    return aps->getOutputForAttr(attr, output, session, stream, pid, uid,
                                  config,
                                  flags, selectedDeviceId, portId);
 }
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index c0e53b3..6478975 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -174,6 +174,7 @@
                                         audio_io_handle_t *output,
                                         audio_session_t session,
                                         audio_stream_type_t *stream,
+                                        pid_t pid,
                                         uid_t uid,
                                         const audio_config_t *config,
                                         audio_output_flags_t flags,
@@ -217,6 +218,7 @@
                 data.writeInt32(1);
                 data.writeInt32(*stream);
             }
+            data.writeInt32(pid);
             data.writeInt32(uid);
             data.write(config, sizeof(audio_config_t));
             data.writeInt32(static_cast <uint32_t>(flags));
@@ -968,6 +970,7 @@
             if (hasStream) {
                 stream = (audio_stream_type_t)data.readInt32();
             }
+            pid_t pid = (pid_t)data.readInt32();
             uid_t uid = (uid_t)data.readInt32();
             audio_config_t config;
             memset(&config, 0, sizeof(audio_config_t));
@@ -978,7 +981,7 @@
             audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
             audio_io_handle_t output = 0;
             status_t status = getOutputForAttr(hasAttributes ? &attr : NULL,
-                    &output, session, &stream, uid,
+                    &output, session, &stream, pid, uid,
                     &config,
                     flags, &selectedDeviceId, &portId);
             reply->writeInt32(status);
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index d6cc37a..e452837 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -216,6 +216,7 @@
                                      audio_io_handle_t *output,
                                      audio_session_t session,
                                      audio_stream_type_t *stream,
+                                     pid_t pid,
                                      uid_t uid,
                                      const audio_config_t *config,
                                      audio_output_flags_t flags,
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 7e9413d..5338927 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -60,6 +60,7 @@
                                       audio_io_handle_t *output,
                                       audio_session_t session,
                                       audio_stream_type_t *stream,
+                                      pid_t pid,
                                       uid_t uid,
                                       const audio_config_t *config,
                                       audio_output_flags_t flags,
diff --git a/media/libaudiohal/2.0/Android.bp b/media/libaudiohal/2.0/Android.bp
new file mode 100644
index 0000000..574b435
--- /dev/null
+++ b/media/libaudiohal/2.0/Android.bp
@@ -0,0 +1,54 @@
+cc_library_shared {
+    name: "libaudiohal@2.0",
+
+    srcs: [
+        "DeviceHalLocal.cpp",
+        "DevicesFactoryHalHybrid.cpp",
+        "DevicesFactoryHalLocal.cpp",
+        "StreamHalLocal.cpp",
+
+        "ConversionHelperHidl.cpp",
+        "DeviceHalHidl.cpp",
+        "DevicesFactoryHalHidl.cpp",
+        "EffectBufferHalHidl.cpp",
+        "EffectHalHidl.cpp",
+        "EffectsFactoryHalHidl.cpp",
+        "StreamHalHidl.cpp",
+    ],
+
+    export_include_dirs: ["."],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libaudiohal_deathhandler",
+        "libaudioutils",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libhardware",
+        "libbase",
+        "libfmq",
+        "libhwbinder",
+        "libhidlbase",
+        "libhidlmemory",
+        "libhidltransport",
+        "android.hardware.audio@2.0",
+        "android.hardware.audio.common@2.0",
+        "android.hardware.audio.common@2.0-util",
+        "android.hardware.audio.effect@2.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libmedia_helper",
+        "libmediautils",
+    ],
+    header_libs: [
+        "libaudiohal_headers"
+    ],
+
+    export_shared_lib_headers: [
+        "libfmq",
+    ],
+}
diff --git a/media/libaudiohal/ConversionHelperHidl.cpp b/media/libaudiohal/2.0/ConversionHelperHidl.cpp
similarity index 100%
rename from media/libaudiohal/ConversionHelperHidl.cpp
rename to media/libaudiohal/2.0/ConversionHelperHidl.cpp
diff --git a/media/libaudiohal/ConversionHelperHidl.h b/media/libaudiohal/2.0/ConversionHelperHidl.h
similarity index 100%
rename from media/libaudiohal/ConversionHelperHidl.h
rename to media/libaudiohal/2.0/ConversionHelperHidl.h
diff --git a/media/libaudiohal/DeviceHalHidl.cpp b/media/libaudiohal/2.0/DeviceHalHidl.cpp
similarity index 99%
rename from media/libaudiohal/DeviceHalHidl.cpp
rename to media/libaudiohal/2.0/DeviceHalHidl.cpp
index 49ef991..0d9c6c4 100644
--- a/media/libaudiohal/DeviceHalHidl.cpp
+++ b/media/libaudiohal/2.0/DeviceHalHidl.cpp
@@ -37,6 +37,7 @@
 using ::android::hardware::audio::common::V2_0::AudioPortConfig;
 using ::android::hardware::audio::common::V2_0::AudioMode;
 using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::common::V2_0::HidlUtils;
 using ::android::hardware::audio::V2_0::DeviceAddress;
 using ::android::hardware::audio::V2_0::IPrimaryDevice;
 using ::android::hardware::audio::V2_0::ParameterValue;
diff --git a/media/libaudiohal/DeviceHalHidl.h b/media/libaudiohal/2.0/DeviceHalHidl.h
similarity index 100%
rename from media/libaudiohal/DeviceHalHidl.h
rename to media/libaudiohal/2.0/DeviceHalHidl.h
diff --git a/media/libaudiohal/DeviceHalLocal.cpp b/media/libaudiohal/2.0/DeviceHalLocal.cpp
similarity index 100%
rename from media/libaudiohal/DeviceHalLocal.cpp
rename to media/libaudiohal/2.0/DeviceHalLocal.cpp
diff --git a/media/libaudiohal/DeviceHalLocal.h b/media/libaudiohal/2.0/DeviceHalLocal.h
similarity index 100%
rename from media/libaudiohal/DeviceHalLocal.h
rename to media/libaudiohal/2.0/DeviceHalLocal.h
diff --git a/media/libaudiohal/DevicesFactoryHalHidl.cpp b/media/libaudiohal/2.0/DevicesFactoryHalHidl.cpp
similarity index 100%
rename from media/libaudiohal/DevicesFactoryHalHidl.cpp
rename to media/libaudiohal/2.0/DevicesFactoryHalHidl.cpp
diff --git a/media/libaudiohal/DevicesFactoryHalHidl.h b/media/libaudiohal/2.0/DevicesFactoryHalHidl.h
similarity index 100%
rename from media/libaudiohal/DevicesFactoryHalHidl.h
rename to media/libaudiohal/2.0/DevicesFactoryHalHidl.h
diff --git a/media/libaudiohal/DevicesFactoryHalHybrid.cpp b/media/libaudiohal/2.0/DevicesFactoryHalHybrid.cpp
similarity index 91%
rename from media/libaudiohal/DevicesFactoryHalHybrid.cpp
rename to media/libaudiohal/2.0/DevicesFactoryHalHybrid.cpp
index 8dc1434..77df6b5 100644
--- a/media/libaudiohal/DevicesFactoryHalHybrid.cpp
+++ b/media/libaudiohal/2.0/DevicesFactoryHalHybrid.cpp
@@ -23,11 +23,6 @@
 
 namespace android {
 
-// static
-sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
-    return new DevicesFactoryHalHybrid();
-}
-
 DevicesFactoryHalHybrid::DevicesFactoryHalHybrid()
         : mLocalFactory(new DevicesFactoryHalLocal()),
           mHidlFactory(new DevicesFactoryHalHidl()) {
diff --git a/media/libaudiohal/DevicesFactoryHalHybrid.h b/media/libaudiohal/2.0/DevicesFactoryHalHybrid.h
similarity index 100%
rename from media/libaudiohal/DevicesFactoryHalHybrid.h
rename to media/libaudiohal/2.0/DevicesFactoryHalHybrid.h
diff --git a/media/libaudiohal/DevicesFactoryHalLocal.cpp b/media/libaudiohal/2.0/DevicesFactoryHalLocal.cpp
similarity index 100%
rename from media/libaudiohal/DevicesFactoryHalLocal.cpp
rename to media/libaudiohal/2.0/DevicesFactoryHalLocal.cpp
diff --git a/media/libaudiohal/DevicesFactoryHalLocal.h b/media/libaudiohal/2.0/DevicesFactoryHalLocal.h
similarity index 100%
rename from media/libaudiohal/DevicesFactoryHalLocal.h
rename to media/libaudiohal/2.0/DevicesFactoryHalLocal.h
diff --git a/media/libaudiohal/EffectBufferHalHidl.cpp b/media/libaudiohal/2.0/EffectBufferHalHidl.cpp
similarity index 97%
rename from media/libaudiohal/EffectBufferHalHidl.cpp
rename to media/libaudiohal/2.0/EffectBufferHalHidl.cpp
index 8b5201b..226a500 100644
--- a/media/libaudiohal/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/2.0/EffectBufferHalHidl.cpp
@@ -37,14 +37,12 @@
     return counter++;
 }
 
-// static
-status_t EffectBufferHalInterface::allocate(
+status_t EffectBufferHalHidl::allocate(
         size_t size, sp<EffectBufferHalInterface>* buffer) {
     return mirror(nullptr, size, buffer);
 }
 
-// static
-status_t EffectBufferHalInterface::mirror(
+status_t EffectBufferHalHidl::mirror(
         void* external, size_t size, sp<EffectBufferHalInterface>* buffer) {
     sp<EffectBufferHalInterface> tempBuffer = new EffectBufferHalHidl(size);
     status_t result = static_cast<EffectBufferHalHidl*>(tempBuffer.get())->init();
diff --git a/media/libaudiohal/EffectBufferHalHidl.h b/media/libaudiohal/2.0/EffectBufferHalHidl.h
similarity index 92%
rename from media/libaudiohal/EffectBufferHalHidl.h
rename to media/libaudiohal/2.0/EffectBufferHalHidl.h
index d7a43ae..31e0087 100644
--- a/media/libaudiohal/EffectBufferHalHidl.h
+++ b/media/libaudiohal/2.0/EffectBufferHalHidl.h
@@ -32,6 +32,9 @@
 class EffectBufferHalHidl : public EffectBufferHalInterface
 {
   public:
+    static status_t allocate(size_t size, sp<EffectBufferHalInterface>* buffer);
+    static status_t mirror(void* external, size_t size, sp<EffectBufferHalInterface>* buffer);
+
     virtual audio_buffer_t* audioBuffer();
     virtual void* externalData() const;
 
diff --git a/media/libaudiohal/EffectHalHidl.cpp b/media/libaudiohal/2.0/EffectHalHidl.cpp
similarity index 99%
rename from media/libaudiohal/EffectHalHidl.cpp
rename to media/libaudiohal/2.0/EffectHalHidl.cpp
index f4d1958..4fb032c 100644
--- a/media/libaudiohal/EffectHalHidl.cpp
+++ b/media/libaudiohal/2.0/EffectHalHidl.cpp
@@ -31,6 +31,7 @@
 using ::android::hardware::audio::effect::V2_0::EffectConfigParameters;
 using ::android::hardware::audio::effect::V2_0::MessageQueueFlagBits;
 using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::audio::common::V2_0::HidlUtils;
 using ::android::hardware::audio::common::V2_0::AudioChannelMask;
 using ::android::hardware::audio::common::V2_0::AudioFormat;
 using ::android::hardware::hidl_vec;
diff --git a/media/libaudiohal/EffectHalHidl.h b/media/libaudiohal/2.0/EffectHalHidl.h
similarity index 100%
rename from media/libaudiohal/EffectHalHidl.h
rename to media/libaudiohal/2.0/EffectHalHidl.h
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.cpp b/media/libaudiohal/2.0/EffectsFactoryHalHidl.cpp
similarity index 91%
rename from media/libaudiohal/EffectsFactoryHalHidl.cpp
rename to media/libaudiohal/2.0/EffectsFactoryHalHidl.cpp
index a8081b7..0d40e6d 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/2.0/EffectsFactoryHalHidl.cpp
@@ -20,10 +20,12 @@
 #include <cutils/native_handle.h>
 
 #include "ConversionHelperHidl.h"
+#include "EffectBufferHalHidl.h"
 #include "EffectHalHidl.h"
 #include "EffectsFactoryHalHidl.h"
 #include "HidlUtils.h"
 
+using ::android::hardware::audio::common::V2_0::HidlUtils;
 using ::android::hardware::audio::common::V2_0::Uuid;
 using ::android::hardware::audio::effect::V2_0::IEffect;
 using ::android::hardware::audio::effect::V2_0::Result;
@@ -31,16 +33,6 @@
 
 namespace android {
 
-// static
-sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
-    return new EffectsFactoryHalHidl();
-}
-
-// static
-bool EffectsFactoryHalInterface::isNullUuid(const effect_uuid_t *pEffectUuid) {
-    return memcmp(pEffectUuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t)) == 0;
-}
-
 EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory") {
     mEffectsFactory = IEffectsFactory::getService();
     if (mEffectsFactory == 0) {
@@ -145,4 +137,14 @@
     return processReturn(__FUNCTION__, ret);
 }
 
+status_t EffectsFactoryHalHidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
+    return EffectBufferHalHidl::allocate(size, buffer);
+}
+
+status_t EffectsFactoryHalHidl::mirrorBuffer(void* external, size_t size,
+                          sp<EffectBufferHalInterface>* buffer) {
+    return EffectBufferHalHidl::mirror(external, size, buffer);
+}
+
+
 } // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.h b/media/libaudiohal/2.0/EffectsFactoryHalHidl.h
similarity index 90%
rename from media/libaudiohal/EffectsFactoryHalHidl.h
rename to media/libaudiohal/2.0/EffectsFactoryHalHidl.h
index e89f042..82b5481 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/2.0/EffectsFactoryHalHidl.h
@@ -21,6 +21,8 @@
 #include <android/hardware/audio/effect/2.0/types.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
 
+#include "ConversionHelperHidl.h"
+
 namespace android {
 
 using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
@@ -49,6 +51,10 @@
 
     virtual status_t dumpEffects(int fd);
 
+    status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
+    status_t mirrorBuffer(void* external, size_t size,
+                          sp<EffectBufferHalInterface>* buffer) override;
+
   private:
     friend class EffectsFactoryHalInterface;
 
diff --git a/media/libaudiohal/StreamHalHidl.cpp b/media/libaudiohal/2.0/StreamHalHidl.cpp
similarity index 100%
rename from media/libaudiohal/StreamHalHidl.cpp
rename to media/libaudiohal/2.0/StreamHalHidl.cpp
diff --git a/media/libaudiohal/StreamHalHidl.h b/media/libaudiohal/2.0/StreamHalHidl.h
similarity index 100%
rename from media/libaudiohal/StreamHalHidl.h
rename to media/libaudiohal/2.0/StreamHalHidl.h
diff --git a/media/libaudiohal/StreamHalLocal.cpp b/media/libaudiohal/2.0/StreamHalLocal.cpp
similarity index 100%
rename from media/libaudiohal/StreamHalLocal.cpp
rename to media/libaudiohal/2.0/StreamHalLocal.cpp
diff --git a/media/libaudiohal/StreamHalLocal.h b/media/libaudiohal/2.0/StreamHalLocal.h
similarity index 100%
rename from media/libaudiohal/StreamHalLocal.h
rename to media/libaudiohal/2.0/StreamHalLocal.h
diff --git a/media/libaudiohal/StreamPowerLog.h b/media/libaudiohal/2.0/StreamPowerLog.h
similarity index 100%
rename from media/libaudiohal/StreamPowerLog.h
rename to media/libaudiohal/2.0/StreamPowerLog.h
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 700de8e..7ecb9d8 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -2,46 +2,52 @@
     name: "libaudiohal",
 
     srcs: [
-        "DeviceHalLocal.cpp",
-        "DevicesFactoryHalHybrid.cpp",
-        "DevicesFactoryHalLocal.cpp",
-        "StreamHalLocal.cpp",
-
-        "ConversionHelperHidl.cpp",
-        "HalDeathHandlerHidl.cpp",
-        "DeviceHalHidl.cpp",
-        "DevicesFactoryHalHidl.cpp",
-        "EffectBufferHalHidl.cpp",
-        "EffectHalHidl.cpp",
-        "EffectsFactoryHalHidl.cpp",
-        "StreamHalHidl.cpp",
+        "DevicesFactoryHalInterface.cpp",
+        "EffectsFactoryHalInterface.cpp",
     ],
 
     cflags: [
         "-Wall",
         "-Werror",
     ],
-    export_include_dirs: ["include"],
 
     shared_libs: [
-        "libaudioutils",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "libhardware",
-        "libbase",
-        "libfmq",
-        "libhwbinder",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
         "android.hardware.audio@2.0",
-        "android.hardware.audio.common@2.0",
-        "android.hardware.audio.common@2.0-util",
         "android.hardware.audio.effect@2.0",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "libmedia_helper",
-        "libmediautils",
+        "libaudiohal@2.0",
+        "libutils",
     ],
+
+    header_libs: [
+        "libaudiohal_headers"
+    ]
+}
+
+cc_library_shared {
+    name: "libaudiohal_deathhandler",
+
+    srcs: [
+        "HalDeathHandlerHidl.cpp",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    shared_libs: [
+        "libhidlbase",
+        "libutils",
+        "liblog",
+    ],
+
+    header_libs: [
+        "libaudiohal_headers"
+    ]
+}
+
+cc_library_headers {
+    name: "libaudiohal_headers",
+
+    export_include_dirs: ["include"],
 }
diff --git a/media/libaudiohal/DevicesFactoryHalInterface.cpp b/media/libaudiohal/DevicesFactoryHalInterface.cpp
new file mode 100644
index 0000000..cfec3d6
--- /dev/null
+++ b/media/libaudiohal/DevicesFactoryHalInterface.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 "DevicesFactoryHalHybrid.h"
+#include <android/hardware/audio/2.0/IDevicesFactory.h>
+
+using namespace ::android::hardware::audio;
+
+namespace android {
+
+// static
+sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
+    if (V2_0::IDevicesFactory::getService() != nullptr) {
+        return new DevicesFactoryHalHybrid();
+    }
+    return nullptr;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalInterface.cpp b/media/libaudiohal/EffectsFactoryHalInterface.cpp
new file mode 100644
index 0000000..01a171e
--- /dev/null
+++ b/media/libaudiohal/EffectsFactoryHalInterface.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectsFactoryHalHidl"
+//#define LOG_NDEBUG 0
+
+#include "EffectHalHidl.h"
+#include "EffectsFactoryHalHidl.h"
+
+using ::android::hardware::Return;
+
+using namespace ::android::hardware::audio::effect;
+
+namespace android {
+
+// static
+sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
+    if (V2_0::IEffectsFactory::getService() != nullptr) {
+        return new EffectsFactoryHalHidl();
+    }
+    return nullptr;
+}
+
+// static
+bool EffectsFactoryHalInterface::isNullUuid(const effect_uuid_t *pEffectUuid) {
+    return memcmp(pEffectUuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t)) == 0;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
index 1cae662..d0603cd 100644
--- a/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectBufferHalInterface.h
@@ -26,6 +26,7 @@
 // Abstraction for an audio buffer. It may be a "mirror" for
 // a buffer that the effect chain doesn't own, or a buffer owned by
 // the effect chain.
+// Buffers are created from EffectsFactoryHalInterface
 class EffectBufferHalInterface : public RefBase
 {
   public:
@@ -49,9 +50,6 @@
     virtual void update(size_t size) = 0;  // copies partial data from external buffer
     virtual void commit(size_t size) = 0;  // copies partial data to external buffer
 
-    static status_t allocate(size_t size, sp<EffectBufferHalInterface>* buffer);
-    static status_t mirror(void* external, size_t size, sp<EffectBufferHalInterface>* buffer);
-
   protected:
     // Subclasses can not be constructed directly by clients.
     EffectBufferHalInterface() {}
diff --git a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
index a616e86..316a46c 100644
--- a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
@@ -48,6 +48,10 @@
 
     static sp<EffectsFactoryHalInterface> create();
 
+    virtual status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
+    virtual status_t mirrorBuffer(void* external, size_t size,
+                                  sp<EffectBufferHalInterface>* buffer) = 0;
+
     // Helper function to compare effect uuid to EFFECT_UUID_NULL.
     static bool isNullUuid(const effect_uuid_t *pEffectUuid);
 
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index 862fef6..e19af4a 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -183,7 +183,7 @@
      mOutFrameSize =
              audio_bytes_per_sample(format) * audio_channel_count_from_out_mask(outputChannelMask);
      status_t status;
-     status = EffectBufferHalInterface::mirror(
+     status = mEffectsFactory->mirrorBuffer(
              nullptr, mInFrameSize * bufferFrameCount, &mInBuffer);
      if (status != 0) {
          ALOGE("DownmixerBufferProvider() error %d while creating input buffer", status);
@@ -191,7 +191,7 @@
          mEffectsFactory.clear();
          return;
      }
-     status = EffectBufferHalInterface::mirror(
+     status = mEffectsFactory->mirrorBuffer(
              nullptr, mOutFrameSize * bufferFrameCount, &mOutBuffer);
      if (status != 0) {
          ALOGE("DownmixerBufferProvider() error %d while creating output buffer", status);
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index 9b06047..ae232b5 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -115,6 +115,9 @@
     MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_DIRECT_PCM),
     MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
     MAKE_STRING_FROM_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
+    // FIXME: this cast will be removed when the flag will be
+    // declared in types.hal for audio HAL V4.0 and auto imported to audio-base.h
+    MAKE_STRING_FROM_ENUM((audio_output_flags_t)AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
     TERMINATOR
 };
 
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index cf800b2..8bd0a51 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -457,13 +457,6 @@
       mGeneration(0) {
     CHECK(mLooper != NULL);
 
-    AString mime;
-    CHECK(mOutputFormat->findString("mime", &mime));
-
-    if (!strncasecmp("video/", mime.c_str(), 6)) {
-        mIsVideo = true;
-    }
-
     if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
         mPuller = new Puller(source);
     }
@@ -487,6 +480,7 @@
 }
 
 status_t MediaCodecSource::initEncoder() {
+
     mReflector = new AHandlerReflector<MediaCodecSource>(this);
     mLooper->registerHandler(mReflector);
 
@@ -500,23 +494,12 @@
 
     AString outputMIME;
     CHECK(mOutputFormat->findString("mime", &outputMIME));
+    mIsVideo = outputMIME.startsWithIgnoreCase("video/");
 
-    Vector<AString> matchingCodecs;
-    MediaCodecList::findMatchingCodecs(
-            outputMIME.c_str(), true /* encoder */,
-            ((mFlags & FLAG_PREFER_SOFTWARE_CODEC) ? MediaCodecList::kPreferSoftwareCodecs : 0),
-            &matchingCodecs);
-
+    AString name;
     status_t err = NO_INIT;
-    for (size_t ix = 0; ix < matchingCodecs.size(); ++ix) {
-        mEncoder = MediaCodec::CreateByComponentName(
-                mCodecLooper, matchingCodecs[ix]);
-
-        if (mEncoder == NULL) {
-            continue;
-        }
-
-        ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
+    if (mOutputFormat->findString("testing-name", &name)) {
+        mEncoder = MediaCodec::CreateByComponentName(mCodecLooper, name);
 
         mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
         mEncoder->setCallback(mEncoderActivityNotify);
@@ -526,12 +509,38 @@
                     NULL /* nativeWindow */,
                     NULL /* crypto */,
                     MediaCodec::CONFIGURE_FLAG_ENCODE);
+    } else {
+        Vector<AString> matchingCodecs;
+        MediaCodecList::findMatchingCodecs(
+                outputMIME.c_str(), true /* encoder */,
+                ((mFlags & FLAG_PREFER_SOFTWARE_CODEC) ? MediaCodecList::kPreferSoftwareCodecs : 0),
+                &matchingCodecs);
 
-        if (err == OK) {
-            break;
+        for (size_t ix = 0; ix < matchingCodecs.size(); ++ix) {
+            mEncoder = MediaCodec::CreateByComponentName(
+                    mCodecLooper, matchingCodecs[ix]);
+
+            if (mEncoder == NULL) {
+                continue;
+            }
+
+            ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
+
+            mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
+            mEncoder->setCallback(mEncoderActivityNotify);
+
+            err = mEncoder->configure(
+                        mOutputFormat,
+                        NULL /* nativeWindow */,
+                        NULL /* crypto */,
+                        MediaCodec::CONFIGURE_FLAG_ENCODE);
+
+            if (err == OK) {
+                break;
+            }
+            mEncoder->release();
+            mEncoder = NULL;
         }
-        mEncoder->release();
-        mEncoder = NULL;
     }
 
     if (err != OK) {
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 353a5e4..078c646 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -38,8 +38,6 @@
 
 namespace android {
 
-static const char *kSystemApkPath = "/system/app/MediaComponents/MediaComponents.apk";
-
 // static
 sp<IMediaExtractor> MediaExtractorFactory::Create(
         const sp<DataSource> &source, const char *mime) {
@@ -246,7 +244,7 @@
 }
 
 //static
-void MediaExtractorFactory::RegisterExtractors(
+void MediaExtractorFactory::RegisterExtractorsInApk(
         const char *apkPath, List<sp<ExtractorPlugin>> &pluginList) {
     ALOGV("search for plugins at %s", apkPath);
     ZipArchiveHandle zipHandle;
@@ -265,6 +263,8 @@
             while (Next(cookie, &entry, &name) == 0) {
                 String8 libPath = String8(apkPath) + "!/" +
                     String8(reinterpret_cast<const char*>(name.name), name.name_length);
+                // TODO: Open with a linker namespace so that it can be linked with sub-libraries
+                // within the apk instead of system libraries already loaded.
                 void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
                 if (libHandle) {
                     MediaExtractor::GetExtractorDef getDef =
@@ -291,6 +291,38 @@
     }
 }
 
+//static
+void MediaExtractorFactory::RegisterExtractorsInSystem(
+        const char *libDirPath, List<sp<ExtractorPlugin>> &pluginList) {
+    ALOGV("search for plugins at %s", libDirPath);
+    DIR *libDir = opendir(libDirPath);
+    if (libDir) {
+        struct dirent* libEntry;
+        while ((libEntry = readdir(libDir))) {
+            String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
+            void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
+            if (libHandle) {
+                MediaExtractor::GetExtractorDef getDef =
+                    (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
+                if (getDef) {
+                    ALOGV("registering sniffer for %s", libPath.string());
+                    RegisterExtractor(
+                            new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
+                } else {
+                    ALOGW("%s does not contain sniffer", libPath.string());
+                    dlclose(libHandle);
+                }
+            } else {
+                ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno));
+            }
+        }
+
+        closedir(libDir);
+    } else {
+        ALOGE("couldn't opendir(%s)", libDirPath);
+    }
+}
+
 // static
 void MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) {
     Mutex::Autolock autoLock(gPluginMutex);
@@ -303,10 +335,20 @@
 
     std::shared_ptr<List<sp<ExtractorPlugin>>> newList(new List<sp<ExtractorPlugin>>());
 
-    RegisterExtractors(kSystemApkPath, *newList);
+    RegisterExtractorsInSystem("/system/lib"
+#ifdef __LP64__
+            "64"
+#endif
+            "/extractors", *newList);
+
+    RegisterExtractorsInSystem("/vendor/lib"
+#ifdef __LP64__
+            "64"
+#endif
+            "/extractors", *newList);
 
     if (newUpdateApkPath != nullptr) {
-        RegisterExtractors(newUpdateApkPath, *newList);
+        RegisterExtractorsInApk(newUpdateApkPath, *newList);
     }
 
     gPlugins = newList;
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index daa9d3f..555e77b 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -405,6 +405,7 @@
     // TODO: move this also into a .so so it can be updated
     mComponents.emplace("c2.google.avc.decoder", "libstagefright_soft_c2avcdec.so");
     mComponents.emplace("c2.google.aac.decoder", "libstagefright_soft_c2aacdec.so");
+    mComponents.emplace("c2.google.aac.encoder", "libstagefright_soft_c2aacenc.so");
 }
 
 c2_status_t C2PlatformComponentStore::copyBuffer(
diff --git a/media/libstagefright/codecs/aacenc/Android.bp b/media/libstagefright/codecs/aacenc/Android.bp
index 9342351..4caef92 100644
--- a/media/libstagefright/codecs/aacenc/Android.bp
+++ b/media/libstagefright/codecs/aacenc/Android.bp
@@ -1,4 +1,42 @@
 cc_library_shared {
+    name: "libstagefright_soft_c2aacenc",
+//    vendor_available: true,
+//    vndk: {
+//        enabled: true,
+//    },
+
+    srcs: ["C2SoftAacEnc.cpp"],
+
+    cflags: ["-Werror"],
+
+    sanitize: {
+        misc_undefined: [
+            "signed-integer-overflow",
+            "unsigned-integer-overflow",
+        ],
+        cfi: true,
+        diag: {
+            cfi: true,
+        },
+    },
+
+    static_libs: [
+        "libFraunhoferAAC",
+        "libstagefright_codec2_vndk"
+    ],
+
+    shared_libs: [
+        "libcutils",
+        "libion",
+        "liblog",
+        "libstagefright_codec2",
+        "libstagefright_foundation",
+        "libstagefright_simple_c2component",
+        "libutils",
+    ],
+}
+
+cc_library_shared {
     name: "libstagefright_soft_aacenc",
     vendor_available: true,
     vndk: {
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
new file mode 100644
index 0000000..94308c4
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "C2SoftAacEnc"
+#include <utils/Log.h>
+
+#include <inttypes.h>
+
+#include <C2PlatformSupport.h>
+#include <SimpleC2Interface.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+#include "C2SoftAacEnc.h"
+
+namespace android {
+
+C2SoftAacEnc::C2SoftAacEnc(
+        const char *name,
+        c2_node_id_t id)
+    : SimpleC2Component(
+            SimpleC2Interface::Builder(name, id)
+            .inputFormat(C2FormatAudio)
+            .outputFormat(C2FormatCompressed)
+            .build()),
+      mAACEncoder(NULL),
+      mNumChannels(1),
+      mSampleRate(44100),
+      mBitRate(64000),
+      mSBRMode(-1),
+      mSBRRatio(0),
+      mAACProfile(AOT_AAC_LC),
+      mNumBytesPerInputFrame(0u),
+      mOutBufferSize(0u),
+      mSentCodecSpecificData(false),
+      mInputSize(0),
+      mInputTimeUs(-1ll),
+      mSignalledError(false) {
+}
+
+C2SoftAacEnc::~C2SoftAacEnc() {
+    onReset();
+}
+
+c2_status_t C2SoftAacEnc::onInit() {
+    status_t err = initEncoder();
+    return err == OK ? C2_OK : C2_CORRUPTED;
+}
+
+status_t C2SoftAacEnc::initEncoder() {
+    if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
+        ALOGE("Failed to init AAC encoder");
+        return UNKNOWN_ERROR;
+    }
+    return setAudioParams();
+}
+
+c2_status_t C2SoftAacEnc::onStop() {
+    mSentCodecSpecificData = false;
+    mInputSize = 0u;
+    mInputTimeUs = -1ll;
+    mSignalledError = false;
+    return C2_OK;
+}
+
+void C2SoftAacEnc::onReset() {
+    (void)onStop();
+    aacEncClose(&mAACEncoder);
+}
+
+void C2SoftAacEnc::onRelease() {
+    // no-op
+}
+
+c2_status_t C2SoftAacEnc::onFlush_sm() {
+    mSentCodecSpecificData = false;
+    mInputSize = 0u;
+    return C2_OK;
+}
+
+static CHANNEL_MODE getChannelMode(uint32_t nChannels) {
+    CHANNEL_MODE chMode = MODE_INVALID;
+    switch (nChannels) {
+        case 1: chMode = MODE_1; break;
+        case 2: chMode = MODE_2; break;
+        case 3: chMode = MODE_1_2; break;
+        case 4: chMode = MODE_1_2_1; break;
+        case 5: chMode = MODE_1_2_2; break;
+        case 6: chMode = MODE_1_2_2_1; break;
+        default: chMode = MODE_INVALID;
+    }
+    return chMode;
+}
+
+//static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
+//    if (profile == OMX_AUDIO_AACObjectLC) {
+//        return AOT_AAC_LC;
+//    } else if (profile == OMX_AUDIO_AACObjectHE) {
+//        return AOT_SBR;
+//    } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
+//        return AOT_PS;
+//    } else if (profile == OMX_AUDIO_AACObjectLD) {
+//        return AOT_ER_AAC_LD;
+//    } else if (profile == OMX_AUDIO_AACObjectELD) {
+//        return AOT_ER_AAC_ELD;
+//    } else {
+//        ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
+//        return AOT_AAC_LC;
+//    }
+//}
+
+status_t C2SoftAacEnc::setAudioParams() {
+    // We call this whenever sample rate, number of channels, bitrate or SBR mode change
+    // in reponse to setParameter calls.
+
+    ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
+         mSampleRate, mNumChannels, mBitRate, mSBRMode, mSBRRatio);
+
+    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, mAACProfile)) {
+        ALOGE("Failed to set AAC encoder parameters");
+        return UNKNOWN_ERROR;
+    }
+
+    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) {
+        ALOGE("Failed to set AAC encoder parameters");
+        return UNKNOWN_ERROR;
+    }
+    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) {
+        ALOGE("Failed to set AAC encoder parameters");
+        return UNKNOWN_ERROR;
+    }
+    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
+            getChannelMode(mNumChannels))) {
+        ALOGE("Failed to set AAC encoder parameters");
+        return UNKNOWN_ERROR;
+    }
+    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
+        ALOGE("Failed to set AAC encoder parameters");
+        return UNKNOWN_ERROR;
+    }
+
+    if (mSBRMode != -1 && mAACProfile == AOT_ER_AAC_ELD) {
+        if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
+            ALOGE("Failed to set AAC encoder parameters");
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    /* SBR ratio parameter configurations:
+       0: Default configuration wherein SBR ratio is configured depending on audio object type by
+          the FDK.
+       1: Downsampled SBR (default for ELD)
+       2: Dualrate SBR (default for HE-AAC)
+     */
+    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
+        ALOGE("Failed to set AAC encoder parameters");
+        return UNKNOWN_ERROR;
+    }
+
+    return OK;
+}
+
+void C2SoftAacEnc::process(
+        const std::unique_ptr<C2Work> &work,
+        const std::shared_ptr<C2BlockPool> &pool) {
+    work->worklets_processed = 0u;
+
+    if (mSignalledError) {
+        return;
+    }
+    bool eos = (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) != 0;
+
+    if (!mSentCodecSpecificData) {
+        // The very first thing we want to output is the codec specific
+        // data.
+
+        if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
+            ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
+            // TODO: notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+            mSignalledError = true;
+            return;
+        }
+
+        uint32_t actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
+        if (mBitRate != actualBitRate) {
+            ALOGW("Requested bitrate %u unsupported, using %u", mBitRate, actualBitRate);
+        }
+
+        AACENC_InfoStruct encInfo;
+        if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
+            ALOGE("Failed to get AAC encoder info");
+            // TODO: notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+            mSignalledError = true;
+            return;
+        }
+
+        std::unique_ptr<C2StreamCsdInfo::output> csd =
+            C2StreamCsdInfo::output::alloc_unique(encInfo.confSize, 0u);
+        // TODO: check NO_MEMORY
+        memcpy(csd->m.value, encInfo.confBuf, encInfo.confSize);
+        ALOGV("put csd");
+#if defined(LOG_NDEBUG) && !LOG_NDEBUG
+        hexdump(csd->m.value, csd->flexCount());
+#endif
+        work->worklets.front()->output.infos.push_back(std::move(csd));
+
+        mOutBufferSize = encInfo.maxOutBufBytes;
+        mNumBytesPerInputFrame = encInfo.frameLength * mNumChannels * sizeof(int16_t);
+        mInputTimeUs = work->input.ordinal.timestamp;
+
+        mSentCodecSpecificData = true;
+    }
+
+    C2ReadView view = work->input.buffers[0]->data().linearBlocks().front().map().get();
+    uint64_t timestamp = mInputTimeUs;
+
+    size_t numFrames = (view.capacity() + mInputSize + (eos ? mNumBytesPerInputFrame - 1 : 0))
+            / mNumBytesPerInputFrame;
+    ALOGV("capacity = %u; mInputSize = %zu; numFrames = %zu", view.capacity(), mInputSize, numFrames);
+
+    std::shared_ptr<C2LinearBlock> block;
+    std::unique_ptr<C2WriteView> wView;
+    uint8_t *outPtr = nullptr;
+    size_t outAvailable = 0u;
+
+    if (numFrames) {
+        C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
+        // TODO: error handling, proper usage, etc.
+        c2_status_t err = pool->fetchLinearBlock(mOutBufferSize * numFrames, usage, &block);
+        if (err != C2_OK) {
+            ALOGE("err = %d", err);
+        }
+
+        wView.reset(new C2WriteView(block->map().get()));
+        outPtr = wView->data();
+        outAvailable = wView->size();
+    }
+
+    AACENC_InArgs inargs;
+    AACENC_OutArgs outargs;
+    memset(&inargs, 0, sizeof(inargs));
+    memset(&outargs, 0, sizeof(outargs));
+    inargs.numInSamples = view.capacity() / sizeof(int16_t);
+
+    void* inBuffer[]        = { (unsigned char *)view.data() };
+    INT   inBufferIds[]     = { IN_AUDIO_DATA };
+    INT   inBufferSize[]    = { (INT)view.capacity() };
+    INT   inBufferElSize[]  = { sizeof(int16_t) };
+
+    AACENC_BufDesc inBufDesc;
+    inBufDesc.numBufs           = sizeof(inBuffer) / sizeof(void*);
+    inBufDesc.bufs              = (void**)&inBuffer;
+    inBufDesc.bufferIdentifiers = inBufferIds;
+    inBufDesc.bufSizes          = inBufferSize;
+    inBufDesc.bufElSizes        = inBufferElSize;
+
+    void* outBuffer[]       = { outPtr };
+    INT   outBufferIds[]    = { OUT_BITSTREAM_DATA };
+    INT   outBufferSize[]   = { 0 };
+    INT   outBufferElSize[] = { sizeof(UCHAR) };
+
+    AACENC_BufDesc outBufDesc;
+    outBufDesc.numBufs           = sizeof(outBuffer) / sizeof(void*);
+    outBufDesc.bufs              = (void**)&outBuffer;
+    outBufDesc.bufferIdentifiers = outBufferIds;
+    outBufDesc.bufSizes          = outBufferSize;
+    outBufDesc.bufElSizes        = outBufferElSize;
+
+    // Encode the mInputFrame, which is treated as a modulo buffer
+    AACENC_ERROR encoderErr = AACENC_OK;
+    size_t nOutputBytes = 0;
+
+    while (encoderErr == AACENC_OK && inargs.numInSamples > 0) {
+        memset(&outargs, 0, sizeof(outargs));
+
+        outBuffer[0] = outPtr;
+        outBufferSize[0] = outAvailable - nOutputBytes;
+
+        encoderErr = aacEncEncode(mAACEncoder,
+                                  &inBufDesc,
+                                  &outBufDesc,
+                                  &inargs,
+                                  &outargs);
+
+        if (encoderErr == AACENC_OK) {
+            if (outargs.numOutBytes > 0) {
+                mInputSize = 0;
+                int consumed = ((view.capacity() / sizeof(int16_t)) - inargs.numInSamples);
+                mInputTimeUs = work->input.ordinal.timestamp
+                        + (consumed * 1000000ll / mNumChannels / mSampleRate);
+            } else {
+                mInputSize += outargs.numInSamples * sizeof(int16_t);
+                mInputTimeUs += outargs.numInSamples * 1000000ll / mNumChannels / mSampleRate;
+            }
+            outPtr += outargs.numOutBytes;
+            nOutputBytes += outargs.numOutBytes;
+
+            if (outargs.numInSamples > 0) {
+                inBuffer[0] = (int16_t *)inBuffer[0] + outargs.numInSamples;
+                inBufferSize[0] -= outargs.numInSamples * sizeof(int16_t);
+                inargs.numInSamples -= outargs.numInSamples;
+            }
+        }
+        ALOGV("nOutputBytes = %zu; inargs.numInSamples = %d", nOutputBytes, inargs.numInSamples);
+    }
+
+    if (eos && inBufferSize[0] > 0) {
+        memset(&outargs, 0, sizeof(outargs));
+
+        outBuffer[0] = outPtr;
+        outBufferSize[0] = outAvailable - nOutputBytes;
+
+        // Flush
+        inargs.numInSamples = -1;
+
+        (void)aacEncEncode(mAACEncoder,
+                           &inBufDesc,
+                           &outBufDesc,
+                           &inargs,
+                           &outargs);
+
+        nOutputBytes += outargs.numOutBytes;
+    }
+
+    work->worklets.front()->output.flags =
+        (C2BufferPack::flags_t)(eos ? C2BufferPack::FLAG_END_OF_STREAM : 0);
+    work->worklets.front()->output.buffers.clear();
+    work->worklets.front()->output.ordinal = work->input.ordinal;
+    work->worklets.front()->output.ordinal.timestamp = timestamp;
+    work->worklets_processed = 1u;
+    if (nOutputBytes) {
+        work->worklets.front()->output.buffers.push_back(
+                createLinearBuffer(block, 0, nOutputBytes));
+    } else {
+        work->worklets.front()->output.buffers.emplace_back(nullptr);
+    }
+
+#if 0
+    ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
+          nOutputBytes, mInputTimeUs, outHeader->nFlags);
+
+    hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
+#endif
+}
+
+c2_status_t C2SoftAacEnc::drain(
+        uint32_t drainMode,
+        const std::shared_ptr<C2BlockPool> &pool) {
+    switch (drainMode) {
+        case DRAIN_COMPONENT_NO_EOS:  // fall-through
+        case NO_DRAIN:
+            // no-op
+            return C2_OK;
+        case DRAIN_CHAIN:
+            return C2_OMITTED;
+        case DRAIN_COMPONENT_WITH_EOS:
+            break;
+        default:
+            return C2_BAD_VALUE;
+    }
+
+    (void)pool;
+    mSentCodecSpecificData = false;
+    mInputSize = 0u;
+
+    // TODO: we don't have any pending work at this time to drain.
+    return C2_OK;
+}
+
+class C2SoftAacEncFactory : public C2ComponentFactory {
+public:
+    virtual c2_status_t createComponent(
+            c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+            std::function<void(::android::C2Component*)> deleter) override {
+        *component = std::shared_ptr<C2Component>(new C2SoftAacEnc("aacenc", id), deleter);
+        return C2_OK;
+    }
+
+    virtual c2_status_t createInterface(
+            c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+            std::function<void(::android::C2ComponentInterface*)> deleter) override {
+        *interface =
+                SimpleC2Interface::Builder("aacenc", id, deleter)
+                .inputFormat(C2FormatAudio)
+                .outputFormat(C2FormatCompressed)
+                .build();
+        return C2_OK;
+    }
+
+    virtual ~C2SoftAacEncFactory() override = default;
+};
+
+}  // namespace android
+
+extern "C" ::android::C2ComponentFactory* CreateCodec2Factory() {
+    ALOGV("in %s", __func__);
+    return new ::android::C2SoftAacEncFactory();
+}
+
+extern "C" void DestroyCodec2Factory(::android::C2ComponentFactory* factory) {
+    ALOGV("in %s", __func__);
+    delete factory;
+}
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h
new file mode 100644
index 0000000..947c960
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2018 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 C2_SOFT_AAC_ENC_H_
+
+#define C2_SOFT_AAC_ENC_H_
+
+#include <SimpleC2Component.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#include "aacenc_lib.h"
+
+namespace android {
+
+class C2SoftAacEnc : public SimpleC2Component {
+public:
+    C2SoftAacEnc(const char *name, c2_node_id_t id);
+    virtual ~C2SoftAacEnc();
+
+    // From SimpleC2Component
+    c2_status_t onInit() override;
+    c2_status_t onStop() override;
+    void onReset() override;
+    void onRelease() override;
+    c2_status_t onFlush_sm() override;
+    void process(
+            const std::unique_ptr<C2Work> &work,
+            const std::shared_ptr<C2BlockPool> &pool) override;
+    c2_status_t drain(
+            uint32_t drainMode,
+            const std::shared_ptr<C2BlockPool> &pool) override;
+
+private:
+    HANDLE_AACENCODER mAACEncoder;
+
+    uint32_t mNumChannels;
+    uint32_t mSampleRate;
+    uint32_t mBitRate;
+    int32_t mSBRMode;
+    int32_t mSBRRatio;
+    AUDIO_OBJECT_TYPE mAACProfile;
+    UINT mNumBytesPerInputFrame;
+    UINT mOutBufferSize;
+
+    bool mSentCodecSpecificData;
+    size_t mInputSize;
+    int64_t mInputTimeUs;
+
+    bool mSignalledError;
+
+    status_t initEncoder();
+
+    status_t setAudioParams();
+
+    DISALLOW_EVIL_CONSTRUCTORS(C2SoftAacEnc);
+};
+
+}  // namespace android
+
+#endif  // C2_SOFT_AAC_ENC_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 55654f1..e5c67e1 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -48,8 +48,10 @@
     static std::shared_ptr<List<sp<ExtractorPlugin>>> gPlugins;
     static bool gPluginsRegistered;
 
-    static void RegisterExtractors(
+    static void RegisterExtractorsInApk(
             const char *apkPath, List<sp<ExtractorPlugin>> &pluginList);
+    static void RegisterExtractorsInSystem(
+            const char *libDirPath, List<sp<ExtractorPlugin>> &pluginList);
     static void RegisterExtractor(
             const sp<ExtractorPlugin> &plugin, List<sp<ExtractorPlugin>> &pluginList);
 
diff --git a/packages/MediaComponents/Android.mk b/packages/MediaComponents/Android.mk
index bbd2afa..bb3dc99 100644
--- a/packages/MediaComponents/Android.mk
+++ b/packages/MediaComponents/Android.mk
@@ -34,22 +34,19 @@
 
 LOCAL_JAVA_LIBRARIES += android-support-annotations
 
-# Embed native libraries in package, rather than installing to /system/lib*.
-# TODO: Find a right way to include libs in the apk. b/72066556
-LOCAL_MODULE_TAGS := samples
-
 # To embed native libraries in package, uncomment the lines below.
-LOCAL_JNI_SHARED_LIBRARIES := \
-    libaacextractor \
-    libamrextractor \
-    libflacextractor \
-    libmidiextractor \
-    libmkvextractor \
-    libmp3extractor \
-    libmp4extractor \
-    libmpeg2extractor \
-    liboggextractor \
-    libwavextractor \
+#LOCAL_MODULE_TAGS := samples
+#LOCAL_JNI_SHARED_LIBRARIES := \
+#    libaacextractor \
+#    libamrextractor \
+#    libflacextractor \
+#    libmidiextractor \
+#    libmkvextractor \
+#    libmp3extractor \
+#    libmp4extractor \
+#    libmpeg2extractor \
+#    liboggextractor \
+#    libwavextractor \
 
 # TODO: Remove dependency with other support libraries.
 LOCAL_STATIC_ANDROID_LIBRARIES += \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a9d0054..686e3e3 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -309,7 +309,7 @@
         fullConfig.format = config->format;
         ret = AudioSystem::getOutputForAttr(attr, &io,
                                             actualSessionId,
-                                            &streamType, client.clientUid,
+                                            &streamType, client.clientPid, client.clientUid,
                                             &fullConfig,
                                             (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
                                                     AUDIO_OUTPUT_FLAG_DIRECT),
@@ -690,7 +690,7 @@
     output.selectedDeviceId = input.selectedDeviceId;
 
     lStatus = AudioSystem::getOutputForAttr(&input.attr, &output.outputId, sessionId, &streamType,
-                                            clientUid, &input.config, input.flags,
+                                            clientPid, clientUid, &input.config, input.flags,
                                             &output.selectedDeviceId, &portId);
 
     if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index b13e551..979290f 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1027,7 +1027,9 @@
                 || size > mInConversionBuffer->getSize())) {
             mInConversionBuffer.clear();
             ALOGV("%s: allocating mInConversionBuffer %zu", __func__, size);
-            (void)EffectBufferHalInterface::allocate(size, &mInConversionBuffer);
+            sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
+            LOG_ALWAYS_FATAL_IF(audioFlinger == nullptr, "EM could not retrieved audioFlinger");
+            (void)audioFlinger->mEffectsFactoryHal->allocateBuffer(size, &mInConversionBuffer);
         }
         if (mInConversionBuffer.get() != nullptr) {
             mInConversionBuffer->setFrameCount(inFrameCount);
@@ -1071,7 +1073,9 @@
                 || size > mOutConversionBuffer->getSize())) {
             mOutConversionBuffer.clear();
             ALOGV("%s: allocating mOutConversionBuffer %zu", __func__, size);
-            (void)EffectBufferHalInterface::allocate(size, &mOutConversionBuffer);
+            sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
+            LOG_ALWAYS_FATAL_IF(audioFlinger == nullptr, "EM could not retrieved audioFlinger");
+            (void)audioFlinger->mEffectsFactoryHal->allocateBuffer(size, &mOutConversionBuffer);
         }
         if (mOutConversionBuffer.get() != nullptr) {
             mOutConversionBuffer->setFrameCount(outFrameCount);
@@ -2020,10 +2024,10 @@
         size_t numSamples = thread->frameCount();
         sp<EffectBufferHalInterface> halBuffer;
 #ifdef FLOAT_EFFECT_CHAIN
-        status_t result = EffectBufferHalInterface::allocate(
+        status_t result = thread->mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
                 numSamples * sizeof(float), &halBuffer);
 #else
-        status_t result = EffectBufferHalInterface::allocate(
+        status_t result = thread->mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
                 numSamples * sizeof(int32_t), &halBuffer);
 #endif
         if (result != OK) return result;
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index c1044ef..f08698e 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -153,4 +153,11 @@
     return ok;
 }
 
+bool modifyPhoneStateAllowed(pid_t pid, uid_t uid) {
+    static const String16 sModifyPhoneState("android.permission.MODIFY_PHONE_STATE");
+    bool ok = checkPermission(sModifyPhoneState, pid, uid);
+    if (!ok) ALOGE("Request requires android.permission.MODIFY_PHONE_STATE");
+    return ok;
+}
+
 } // namespace android
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
index 04cb9cd..83533dd 100644
--- a/services/audioflinger/ServiceUtilities.h
+++ b/services/audioflinger/ServiceUtilities.h
@@ -26,4 +26,5 @@
 bool settingsAllowed();
 bool modifyAudioRoutingAllowed();
 bool dumpAllowed();
+bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
 }
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8bf50b1..70ac32c 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -56,6 +56,8 @@
 
 #include <powermanager/PowerManager.h>
 
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+
 #include "AudioFlinger.h"
 #include "FastMixer.h"
 #include "FastCapture.h"
@@ -2882,7 +2884,7 @@
 {
     audio_session_t session = chain->sessionId();
     sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
-    status_t result = EffectBufferHalInterface::mirror(
+    status_t result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
             mEffectBufferEnabled ? mEffectBuffer : mSinkBuffer,
             mEffectBufferEnabled ? mEffectBufferSize : mSinkBufferSize,
             &halInBuffer);
@@ -2895,7 +2897,7 @@
         // the sink buffer as input
         if (mType != DIRECT) {
             size_t numSamples = mNormalFrameCount * mChannelCount;
-            status_t result = EffectBufferHalInterface::allocate(
+            status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
                     numSamples * sizeof(effect_buffer_t),
                     &halInBuffer);
             if (result != OK) return result;
@@ -7819,6 +7821,7 @@
         ret = AudioSystem::getOutputForAttr(&mAttr, &io,
                                             mSessionId,
                                             &stream,
+                                            client.clientPid,
                                             client.clientUid,
                                             &config,
                                             flags,
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 2a8f54d..7f09e9b 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -116,7 +116,7 @@
                                         audio_stream_type_t *stream,
                                         uid_t uid,
                                         const audio_config_t *config,
-                                        audio_output_flags_t flags,
+                                        audio_output_flags_t *flags,
                                         audio_port_handle_t *selectedDeviceId,
                                         audio_port_handle_t *portId) = 0;
     // indicates to the audio policy manager that the output starts being used by corresponding stream.
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 044d6db..d5e8e1b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -333,6 +333,10 @@
             return true;
         }
     }
+    if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
+        ALOGV("max gain when output device is telephony tx");
+        return true;
+    }
     return false;
 }
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 78a02b2..e058dc8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -741,7 +741,7 @@
                                               audio_stream_type_t *stream,
                                               uid_t uid,
                                               const audio_config_t *config,
-                                              audio_output_flags_t flags,
+                                              audio_output_flags_t *flags,
                                               audio_port_handle_t *selectedDeviceId,
                                               audio_port_handle_t *portId)
 {
@@ -801,12 +801,12 @@
     audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
 
     if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
-        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
+        *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
     }
 
     ALOGV("getOutputForAttr() device 0x%x, sampling rate %d, format %#x, channel mask %#x, "
           "flags %#x",
-          device, config->sample_rate, config->format, config->channel_mask, flags);
+          device, config->sample_rate, config->format, config->channel_mask, *flags);
 
     *output = getOutputForDevice(device, session, *stream, config, flags);
     if (*output == AUDIO_IO_HANDLE_NONE) {
@@ -828,7 +828,7 @@
         audio_session_t session,
         audio_stream_type_t stream,
         const audio_config_t *config,
-        audio_output_flags_t flags)
+        audio_output_flags_t *flags)
 {
     audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
     status_t status;
@@ -837,35 +837,41 @@
     //force direct flag if offload flag is set: offloading implies a direct output stream
     // and all common behaviors are driven by checking only the direct flag
     // this should normally be set appropriately in the policy configuration file
-    if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
-        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
+    if ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+        *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT);
     }
-    if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
-        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
+    if ((*flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
+        *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT);
     }
     // only allow deep buffering for music stream type
     if (stream != AUDIO_STREAM_MUSIC) {
-        flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
+        *flags = (audio_output_flags_t)(*flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
     } else if (/* stream == AUDIO_STREAM_MUSIC && */
-            flags == AUDIO_OUTPUT_FLAG_NONE &&
+            *flags == AUDIO_OUTPUT_FLAG_NONE &&
             property_get_bool("audio.deep_buffer.media", false /* default_value */)) {
         // use DEEP_BUFFER as default output for music stream type
-        flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+        *flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
     }
     if (stream == AUDIO_STREAM_TTS) {
-        flags = AUDIO_OUTPUT_FLAG_TTS;
+        *flags = AUDIO_OUTPUT_FLAG_TTS;
     } else if (stream == AUDIO_STREAM_VOICE_CALL &&
                audio_is_linear_pcm(config->format)) {
-        flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_VOIP_RX |
+        *flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_VOIP_RX |
                                        AUDIO_OUTPUT_FLAG_DIRECT);
         ALOGV("Set VoIP and Direct output flags for PCM format");
+    } else if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
+        stream == AUDIO_STREAM_MUSIC &&
+        audio_is_linear_pcm(config->format) &&
+        isInCall()) {
+        *flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
     }
 
+
     sp<IOProfile> profile;
 
     // skip direct output selection if the request can obviously be attached to a mixed output
     // and not explicitly requested
-    if (((flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
+    if (((*flags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
             audio_is_linear_pcm(config->format) && config->sample_rate <= SAMPLE_RATE_HZ_MAX &&
             audio_channel_count_from_out_mask(config->channel_mask) <= 2) {
         goto non_direct_output;
@@ -878,13 +884,13 @@
     // This may prevent offloading in rare situations where effects are left active by apps
     // in the background.
 
-    if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
+    if (((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
             !(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) {
         profile = getProfileForDirectOutput(device,
                                            config->sample_rate,
                                            config->format,
                                            config->channel_mask,
-                                           (audio_output_flags_t)flags);
+                                           (audio_output_flags_t)*flags);
     }
 
     if (profile != 0) {
@@ -916,7 +922,7 @@
         String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->mAddress
                 : String8("");
 
-        status = outputDesc->open(config, device, address, stream, flags, &output);
+        status = outputDesc->open(config, device, address, stream, *flags, &output);
 
         // only accept an output with the requested parameters
         if (status != NO_ERROR ||
@@ -954,7 +960,7 @@
 
     // A request for HW A/V sync cannot fallback to a mixed output because time
     // stamps are embedded in audio data
-    if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
+    if ((*flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
         return AUDIO_IO_HANDLE_NONE;
     }
 
@@ -969,12 +975,12 @@
         SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
 
         // at this stage we should ignore the DIRECT flag as no direct output could be found earlier
-        flags = (audio_output_flags_t)(flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
-        output = selectOutput(outputs, flags, config->format);
+        *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
+        output = selectOutput(outputs, *flags, config->format);
     }
     ALOGW_IF((output == 0), "getOutputForDevice() could not find output for stream %d, "
             "sampling rate %d, format %#x, channels %#x, flags %#x",
-            stream, config->sample_rate, config->format, config->channel_mask, flags);
+            stream, config->sample_rate, config->format, config->channel_mask, *flags);
 
     return output;
 }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 4fd73e6..2b68882 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -110,7 +110,7 @@
                                           audio_stream_type_t *stream,
                                           uid_t uid,
                                           const audio_config_t *config,
-                                          audio_output_flags_t flags,
+                                          audio_output_flags_t *flags,
                                           audio_port_handle_t *selectedDeviceId,
                                           audio_port_handle_t *portId);
         virtual status_t startOutput(audio_io_handle_t output,
@@ -629,7 +629,7 @@
                 audio_session_t session,
                 audio_stream_type_t stream,
                 const audio_config_t *config,
-                audio_output_flags_t flags);
+                audio_output_flags_t *flags);
         // internal method to return the input handle for the given device and format
         audio_io_handle_t getInputForDevice(audio_devices_t device,
                 String8 address,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 680d7b9..f1d7d86 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -158,6 +158,7 @@
                                               audio_io_handle_t *output,
                                               audio_session_t session,
                                               audio_stream_type_t *stream,
+                                              pid_t pid,
                                               uid_t uid,
                                               const audio_config_t *config,
                                               audio_output_flags_t flags,
@@ -176,9 +177,26 @@
                 "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid);
         uid = callingUid;
     }
-    return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
+    audio_output_flags_t originalFlags = flags;
+    status_t result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
                                                  config,
-                                                 flags, selectedDeviceId, portId);
+                                                 &flags, selectedDeviceId, portId);
+
+    // FIXME: Introduce a way to check for the the telephony device before opening the output
+    if ((result == NO_ERROR) &&
+        (flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) &&
+        !modifyPhoneStateAllowed(pid, uid)) {
+        // If the app tries to play music through the telephony device and doesn't have permission
+        // the fallback to the default output device.
+        mAudioPolicyManager->releaseOutput(*output, *stream, session);
+        flags = originalFlags;
+        *selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+        *portId = AUDIO_PORT_HANDLE_NONE;
+        result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
+                                                 config,
+                                                 &flags, selectedDeviceId, portId);
+    }
+    return result;
 }
 
 status_t AudioPolicyService::startOutput(audio_io_handle_t output,
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 9bc13c2..c21aa58 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -78,6 +78,7 @@
                                       audio_io_handle_t *output,
                                       audio_session_t session,
                                       audio_stream_type_t *stream,
+                                      pid_t pid,
                                       uid_t uid,
                                       const audio_config_t *config,
                                       audio_output_flags_t flags,
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 910dd78..e848a3f 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -508,7 +508,7 @@
 
 void CameraClient::releaseRecordingFrameHandle(native_handle_t *handle) {
     if (handle == nullptr) return;
-
+    Mutex::Autolock lock(mLock);
     sp<IMemory> dataPtr;
     {
         Mutex::Autolock l(mAvailableCallbackBuffersLock);
@@ -532,17 +532,22 @@
         return;
     }
 
-    VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
-    metadata->eType = kMetadataBufferTypeNativeHandleSource;
-    metadata->pHandle = handle;
-
-    mHardware->releaseRecordingFrame(dataPtr);
+    if (mHardware != nullptr) {
+        VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
+        metadata->eType = kMetadataBufferTypeNativeHandleSource;
+        metadata->pHandle = handle;
+        mHardware->releaseRecordingFrame(dataPtr);
+    }
 }
 
 void CameraClient::releaseRecordingFrameHandleBatch(const std::vector<native_handle_t*>& handles) {
+    Mutex::Autolock lock(mLock);
+    bool disconnected = (mHardware == nullptr);
     size_t n = handles.size();
     std::vector<sp<IMemory>> frames;
-    frames.reserve(n);
+    if (!disconnected) {
+        frames.reserve(n);
+    }
     bool error = false;
     for (auto& handle : handles) {
         sp<IMemory> dataPtr;
@@ -566,10 +571,12 @@
             break;
         }
 
-        VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
-        metadata->eType = kMetadataBufferTypeNativeHandleSource;
-        metadata->pHandle = handle;
-        frames.push_back(dataPtr);
+        if (!disconnected) {
+            VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(dataPtr->pointer());
+            metadata->eType = kMetadataBufferTypeNativeHandleSource;
+            metadata->pHandle = handle;
+            frames.push_back(dataPtr);
+        }
     }
 
     if (error) {
@@ -577,7 +584,7 @@
             native_handle_close(handle);
             native_handle_delete(handle);
         }
-    } else {
+    } else if (!disconnected) {
         mHardware->releaseRecordingFrameBatch(frames);
     }
     return;
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index 0d2dba1..a71a732 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2012-2018 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.
@@ -154,7 +154,8 @@
                 callbackFormat, params.previewFormat);
         res = device->createStream(mCallbackWindow,
                 params.previewWidth, params.previewHeight, callbackFormat,
-                HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId);
+                HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId,
+                String8());
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index d1bbdaf..cc4249f 100755
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2012-2018 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.
@@ -168,7 +168,8 @@
         res = device->createStream(mCaptureWindow,
                 params.pictureWidth, params.pictureHeight,
                 HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_V0_JFIF,
-                CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId);
+                CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId,
+                String8());
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for capture: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 73dca73..0786f53 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2012-2018 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.
@@ -194,7 +194,7 @@
         res = device->createStream(mPreviewWindow,
                 params.previewWidth, params.previewHeight,
                 CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_UNKNOWN,
-                CAMERA3_STREAM_ROTATION_0, &mPreviewStreamId);
+                CAMERA3_STREAM_ROTATION_0, &mPreviewStreamId, String8());
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
                     __FUNCTION__, mId, strerror(-res), res);
@@ -379,7 +379,8 @@
         res = device->createStream(mRecordingWindow,
                 params.videoWidth, params.videoHeight,
                 params.videoFormat, params.videoDataSpace,
-                CAMERA3_STREAM_ROTATION_0, &mRecordingStreamId);
+                CAMERA3_STREAM_ROTATION_0, &mRecordingStreamId,
+                String8());
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for recording: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index b0607fb..372a2c5 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -311,7 +311,8 @@
 
         res = device->createStream(outSurface, params.fastInfo.arrayWidth,
             params.fastInfo.arrayHeight, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
-            HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mZslStreamId);
+            HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mZslStreamId,
+            String8());
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create ZSL stream: "
                     "%s (%d)", __FUNCTION__, client->getCameraId(),
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 5cbc158..c36c7cf 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -175,7 +175,7 @@
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Empty request list");
     }
 
-    List<const CameraMetadata> metadataRequestList;
+    List<const CameraDeviceBase::PhysicalCameraSettingsList> metadataRequestList;
     std::list<const SurfaceMap> surfaceMapList;
     submitInfo->mRequestId = mRequestIdCounter;
     uint32_t loopCounter = 0;
@@ -193,28 +193,72 @@
                         mCameraIdStr.string());
                 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                         "Repeating reprocess requests not supported");
+            } else if (request.mPhysicalCameraSettings.size() > 1) {
+                ALOGE("%s: Camera %s: reprocess requests not supported for "
+                        "multiple physical cameras.", __FUNCTION__,
+                        mCameraIdStr.string());
+                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        "Reprocess requests not supported for multiple cameras");
             }
         }
 
-        CameraMetadata metadata(request.mMetadata);
-        if (metadata.isEmpty()) {
-            ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
-                   __FUNCTION__, mCameraIdStr.string());
+        if (request.mPhysicalCameraSettings.empty()) {
+            ALOGE("%s: Camera %s: request doesn't contain any settings.", __FUNCTION__,
+                    mCameraIdStr.string());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                    "Request settings are empty");
-        } else if (request.mSurfaceList.isEmpty() && request.mStreamIdxList.size() == 0) {
+                    "Request doesn't contain any settings");
+        }
+
+        //The first capture settings should always match the logical camera id
+        String8 logicalId(request.mPhysicalCameraSettings.begin()->id.c_str());
+        if (mDevice->getId() != logicalId) {
+            ALOGE("%s: Camera %s: Invalid camera request settings.", __FUNCTION__,
+                    mCameraIdStr.string());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                    "Invalid camera request settings");
+        }
+
+        CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
+        for (const auto& it : request.mPhysicalCameraSettings) {
+            String8 physicalId(it.id.c_str());
+            if ((physicalId != mDevice->getId()) && !checkPhysicalCameraId(physicalId)) {
+                ALOGE("%s: Camera %s: Physical camera id: %s is invalid.", __FUNCTION__,
+                        mCameraIdStr.string(), physicalId.string());
+                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        "Invalid physical camera id");
+            }
+
+            CameraMetadata metadata(it.settings);
+            if (metadata.isEmpty()) {
+                ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
+                        __FUNCTION__, mCameraIdStr.string());
+                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        "Request settings are empty");
+            }
+
+            if (!enforceRequestPermissions(metadata)) {
+                // Callee logs
+                return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
+                        "Caller does not have permission to change restricted controls");
+            }
+
+            physicalSettingsList.push_back({it.id, metadata});
+        }
+
+        if (streaming && (physicalSettingsList.size() > 1)) {
+            ALOGE("%s: Camera %s: Individual physical camera settings are not supported in "
+                    "streaming requests. Rejecting request.", __FUNCTION__, mCameraIdStr.string());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                    "Streaming request contains individual physical requests");
+        }
+
+        if (request.mSurfaceList.isEmpty() && request.mStreamIdxList.size() == 0) {
             ALOGE("%s: Camera %s: Requests must have at least one surface target. "
                     "Rejecting request.", __FUNCTION__, mCameraIdStr.string());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                     "Request has no output targets");
         }
 
-        if (!enforceRequestPermissions(metadata)) {
-            // Callee logs
-            return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
-                    "Caller does not have permission to change restricted controls");
-        }
-
         /**
          * Write in the output stream IDs and map from stream ID to surface ID
          * which we calculate from the capture request's list of surface target
@@ -261,20 +305,22 @@
             }
         }
 
-        metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0],
-                        outputStreamIds.size());
+        physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS,
+                &outputStreamIds[0], outputStreamIds.size());
 
         if (request.mIsReprocess) {
-            metadata.update(ANDROID_REQUEST_INPUT_STREAMS, &mInputStream.id, 1);
+            physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_INPUT_STREAMS,
+                    &mInputStream.id, 1);
         }
 
-        metadata.update(ANDROID_REQUEST_ID, &(submitInfo->mRequestId), /*size*/1);
+        physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_ID,
+                &(submitInfo->mRequestId), /*size*/1);
         loopCounter++; // loopCounter starts from 1
         ALOGV("%s: Camera %s: Creating request with ID %d (%d of %zu)",
                 __FUNCTION__, mCameraIdStr.string(), submitInfo->mRequestId,
                 loopCounter, requests.size());
 
-        metadataRequestList.push_back(metadata);
+        metadataRequestList.push_back(physicalSettingsList);
         surfaceMapList.push_back(surfaceMap);
     }
     mRequestIdCounter++;
@@ -508,6 +554,7 @@
     size_t numBufferProducers = bufferProducers.size();
     bool deferredConsumer = outputConfiguration.isDeferred();
     bool isShared = outputConfiguration.isShared();
+    String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
 
     if (numBufferProducers > MAX_SURFACES_PER_STREAM) {
         ALOGE("%s: GraphicBufferProducer count %zu for stream exceeds limit of %d",
@@ -529,6 +576,12 @@
         return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
     }
 
+    if (!checkPhysicalCameraId(physicalCameraId)) {
+        String8 msg = String8::format("Camera %s: Camera doesn't support physicalCameraId %s.",
+                    mCameraIdStr.string(), physicalCameraId.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
     std::vector<sp<Surface>> surfaces;
     std::vector<sp<IBinder>> binders;
     status_t err;
@@ -578,7 +631,8 @@
     err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
             streamInfo.height, streamInfo.format, streamInfo.dataSpace,
             static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
-            &streamId, &surfaceIds, outputConfiguration.getSurfaceSetID(), isShared);
+            &streamId, physicalCameraId, &surfaceIds, outputConfiguration.getSurfaceSetID(),
+            isShared);
 
     if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
@@ -640,10 +694,12 @@
     int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
     std::vector<sp<Surface>> noSurface;
     std::vector<int> surfaceIds;
+    String8 physicalCameraId(outputConfiguration.getPhysicalCameraId());
     err = mDevice->createStream(noSurface, /*hasDeferredConsumer*/true, width,
             height, format, dataSpace,
             static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
-            &streamId, &surfaceIds, outputConfiguration.getSurfaceSetID(), isShared,
+            &streamId, physicalCameraId, &surfaceIds,
+            outputConfiguration.getSurfaceSetID(), isShared,
             consumerUsage);
 
     if (err != OK) {
@@ -1059,6 +1115,43 @@
     return binder::Status::ok();
 }
 
+bool CameraDeviceClient::checkPhysicalCameraId(const String8& physicalCameraId) {
+    if (0 == physicalCameraId.size()) {
+        return true;
+    }
+
+    CameraMetadata staticInfo = mDevice->info();
+    camera_metadata_entry_t entryCap;
+    bool isLogicalCam = false;
+
+    entryCap = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+    for (size_t i = 0; i < entryCap.count; ++i) {
+        uint8_t capability = entryCap.data.u8[i];
+        if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+            isLogicalCam = true;
+        }
+    }
+    if (!isLogicalCam) {
+        return false;
+    }
+
+    camera_metadata_entry_t entryIds = staticInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
+    const uint8_t* ids = entryIds.data.u8;
+    size_t start = 0;
+    for (size_t i = 0; i < entryIds.count; ++i) {
+        if (ids[i] == '\0') {
+            if (start != i) {
+                String8 currentId((const char*)ids+start);
+                if (currentId == physicalCameraId) {
+                    return true;
+                }
+            }
+            start = i+1;
+        }
+    }
+    return false;
+}
+
 bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
         int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
         /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 4086c72..14aeed0 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -262,6 +262,10 @@
             /*out*/SurfaceMap* surfaceMap,
             /*out*/Vector<int32_t>* streamIds);
 
+    // Check that the physicalCameraId passed in is spported by the camera
+    // device.
+    bool checkPhysicalCameraId(const String8& physicalCameraId);
+
     // IGraphicsBufferProducer binder -> Stream ID + Surface ID for output streams
     KeyedVector<sp<IBinder>, StreamSurfaceId> mStreamMap;
 
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 3fd6921..7956be5 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -65,6 +65,12 @@
      */
     virtual const CameraMetadata& info() const = 0;
 
+    struct PhysicalCameraSettings {
+        std::string cameraId;
+        CameraMetadata metadata;
+    };
+    typedef List<PhysicalCameraSettings> PhysicalCameraSettingsList;
+
     /**
      * Submit request for capture. The CameraDevice takes ownership of the
      * passed-in buffer.
@@ -76,7 +82,7 @@
      * Submit a list of requests.
      * Output lastFrameNumber is the expected last frame number of the list of requests.
      */
-    virtual status_t captureList(const List<const CameraMetadata> &requests,
+    virtual status_t captureList(const List<const PhysicalCameraSettingsList> &requests,
                                  const std::list<const SurfaceMap> &surfaceMaps,
                                  int64_t *lastFrameNumber = NULL) = 0;
 
@@ -92,7 +98,7 @@
      * Submit a list of requests for streaming.
      * Output lastFrameNumber is the last frame number of the previous streaming request.
      */
-    virtual status_t setStreamingRequestList(const List<const CameraMetadata> &requests,
+    virtual status_t setStreamingRequestList(const List<const PhysicalCameraSettingsList> &requests,
                                              const std::list<const SurfaceMap> &surfaceMaps,
                                              int64_t *lastFrameNumber = NULL) = 0;
 
@@ -119,6 +125,7 @@
     virtual status_t createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+            const String8& physicalCameraId,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
             bool isShared = false, uint64_t consumerUsage = 0) = 0;
@@ -133,6 +140,7 @@
     virtual status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+            const String8& physicalCameraId,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
             bool isShared = false, uint64_t consumerUsage = 0) = 0;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 2ff200d..f2da232 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -35,6 +35,7 @@
 // Hardcoded name for the passthrough HAL implementation, since it can't be discovered via the
 // service manager
 const std::string kLegacyProviderName("legacy/0");
+const std::string kExternalProviderName("external/0");
 
 // Slash-separated list of provider types to consider for use via the old camera API
 const std::string kStandardProviderTypes("internal/legacy");
@@ -69,6 +70,7 @@
 
     // See if there's a passthrough HAL, but let's not complain if there's not
     addProviderLocked(kLegacyProviderName, /*expected*/ false);
+    addProviderLocked(kExternalProviderName, /*expected*/ false);
 
     return OK;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index d99fc1d..7e71c3b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -194,8 +194,14 @@
 
     mTagMonitor.initialize(mVendorTagId);
 
+    Vector<int32_t> sessionParamKeys;
+    camera_metadata_entry_t sessionKeysEntry = mDeviceInfo.find(
+            ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
+    if (sessionKeysEntry.count > 0) {
+        sessionParamKeys.insertArrayAt(sessionKeysEntry.data.i32, 0, sessionKeysEntry.count);
+    }
     /** Start up request queue thread */
-    mRequestThread = new RequestThread(this, mStatusTracker, mInterface);
+    mRequestThread = new RequestThread(this, mStatusTracker, mInterface, sessionParamKeys);
     res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
     if (res != OK) {
         SET_ERR_L("Unable to start request queue thread: %s (%d)",
@@ -735,7 +741,7 @@
 }
 
 status_t Camera3Device::convertMetadataListToRequestListLocked(
-        const List<const CameraMetadata> &metadataList,
+        const List<const PhysicalCameraSettingsList> &metadataList,
         const std::list<const SurfaceMap> &surfaceMaps,
         bool repeating,
         RequestList *requestList) {
@@ -745,7 +751,7 @@
     }
 
     int32_t burstId = 0;
-    List<const CameraMetadata>::const_iterator metadataIt = metadataList.begin();
+    List<const PhysicalCameraSettingsList>::const_iterator metadataIt = metadataList.begin();
     std::list<const SurfaceMap>::const_iterator surfaceMapIt = surfaceMaps.begin();
     for (; metadataIt != metadataList.end() && surfaceMapIt != surfaceMaps.end();
             ++metadataIt, ++surfaceMapIt) {
@@ -759,12 +765,13 @@
 
         // Setup burst Id and request Id
         newRequest->mResultExtras.burstId = burstId++;
-        if (metadataIt->exists(ANDROID_REQUEST_ID)) {
-            if (metadataIt->find(ANDROID_REQUEST_ID).count == 0) {
+        if (metadataIt->begin()->metadata.exists(ANDROID_REQUEST_ID)) {
+            if (metadataIt->begin()->metadata.find(ANDROID_REQUEST_ID).count == 0) {
                 CLOGE("RequestID entry exists; but must not be empty in metadata");
                 return BAD_VALUE;
             }
-            newRequest->mResultExtras.requestId = metadataIt->find(ANDROID_REQUEST_ID).data.i32[0];
+            newRequest->mResultExtras.requestId = metadataIt->begin()->metadata.find(
+                    ANDROID_REQUEST_ID).data.i32[0];
         } else {
             CLOGE("RequestID does not exist in metadata");
             return BAD_VALUE;
@@ -796,17 +803,19 @@
 status_t Camera3Device::capture(CameraMetadata &request, int64_t* /*lastFrameNumber*/) {
     ATRACE_CALL();
 
-    List<const CameraMetadata> requests;
+    List<const PhysicalCameraSettingsList> requestsList;
     std::list<const SurfaceMap> surfaceMaps;
-    convertToRequestList(requests, surfaceMaps, request);
+    convertToRequestList(requestsList, surfaceMaps, request);
 
-    return captureList(requests, surfaceMaps, /*lastFrameNumber*/NULL);
+    return captureList(requestsList, surfaceMaps, /*lastFrameNumber*/NULL);
 }
 
-void Camera3Device::convertToRequestList(List<const CameraMetadata>& requests,
+void Camera3Device::convertToRequestList(List<const PhysicalCameraSettingsList>& requestsList,
         std::list<const SurfaceMap>& surfaceMaps,
         const CameraMetadata& request) {
-    requests.push_back(request);
+    PhysicalCameraSettingsList requestList;
+    requestList.push_back({std::string(getId().string()), request});
+    requestsList.push_back(requestList);
 
     SurfaceMap surfaceMap;
     camera_metadata_ro_entry streams = request.find(ANDROID_REQUEST_OUTPUT_STREAMS);
@@ -819,7 +828,7 @@
 }
 
 status_t Camera3Device::submitRequestsHelper(
-        const List<const CameraMetadata> &requests,
+        const List<const PhysicalCameraSettingsList> &requests,
         const std::list<const SurfaceMap> &surfaceMaps,
         bool repeating,
         /*out*/
@@ -1069,42 +1078,43 @@
     notify(&m);
 }
 
-status_t Camera3Device::captureList(const List<const CameraMetadata> &requests,
+status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
                                     const std::list<const SurfaceMap> &surfaceMaps,
                                     int64_t *lastFrameNumber) {
     ATRACE_CALL();
 
-    return submitRequestsHelper(requests, surfaceMaps, /*repeating*/false, lastFrameNumber);
+    return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/false, lastFrameNumber);
 }
 
 status_t Camera3Device::setStreamingRequest(const CameraMetadata &request,
                                             int64_t* /*lastFrameNumber*/) {
     ATRACE_CALL();
 
-    List<const CameraMetadata> requests;
+    List<const PhysicalCameraSettingsList> requestsList;
     std::list<const SurfaceMap> surfaceMaps;
-    convertToRequestList(requests, surfaceMaps, request);
+    convertToRequestList(requestsList, surfaceMaps, request);
 
-    return setStreamingRequestList(requests, /*surfaceMap*/surfaceMaps,
+    return setStreamingRequestList(requestsList, /*surfaceMap*/surfaceMaps,
                                    /*lastFrameNumber*/NULL);
 }
 
-status_t Camera3Device::setStreamingRequestList(const List<const CameraMetadata> &requests,
-                                                const std::list<const SurfaceMap> &surfaceMaps,
-                                                int64_t *lastFrameNumber) {
+status_t Camera3Device::setStreamingRequestList(
+        const List<const PhysicalCameraSettingsList> &requestsList,
+        const std::list<const SurfaceMap> &surfaceMaps, int64_t *lastFrameNumber) {
     ATRACE_CALL();
 
-    return submitRequestsHelper(requests, surfaceMaps, /*repeating*/true, lastFrameNumber);
+    return submitRequestsHelper(requestsList, surfaceMaps, /*repeating*/true, lastFrameNumber);
 }
 
 sp<Camera3Device::CaptureRequest> Camera3Device::setUpRequestLocked(
-        const CameraMetadata &request, const SurfaceMap &surfaceMap) {
+        const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
     status_t res;
 
     if (mStatus == STATUS_UNCONFIGURED || mNeedConfig) {
         // This point should only be reached via API1 (API2 must explicitly call configureStreams)
         // so unilaterally select normal operating mode.
-        res = configureStreamsLocked(CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE, mSessionParams);
+        res = filterParamsAndConfigureLocked(request.begin()->metadata,
+                CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE);
         // Stream configuration failed. Client might try other configuraitons.
         if (res != OK) {
             CLOGE("Can't set up streams: %s (%d)", strerror(-res), res);
@@ -1224,6 +1234,7 @@
 status_t Camera3Device::createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+            const String8& physicalCameraId,
             std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
     ATRACE_CALL();
 
@@ -1236,12 +1247,14 @@
     consumers.push_back(consumer);
 
     return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
-            format, dataSpace, rotation, id, surfaceIds, streamSetId, isShared, consumerUsage);
+            format, dataSpace, rotation, id, physicalCameraId, surfaceIds, streamSetId,
+            isShared, consumerUsage);
 }
 
 status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
         bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
         android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+        const String8& physicalCameraId,
         std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
     ATRACE_CALL();
 
@@ -1249,8 +1262,9 @@
     nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
     Mutex::Autolock l(mLock);
     ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
-            " consumer usage %" PRIu64 ", isShared %d", mId.string(), mNextStreamId, width, height, format,
-            dataSpace, rotation, consumerUsage, isShared);
+            " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s", mId.string(),
+            mNextStreamId, width, height, format, dataSpace, rotation, consumerUsage, isShared,
+            physicalCameraId.string());
 
     status_t res;
     bool wasActive = false;
@@ -1310,7 +1324,7 @@
         }
         newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
                 width, height, blobBufferSize, format, dataSpace, rotation,
-                mTimestampOffset, streamSetId);
+                mTimestampOffset, physicalCameraId, streamSetId);
     } else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
         ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
         if (rawOpaqueBufferSize <= 0) {
@@ -1319,19 +1333,19 @@
         }
         newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
                 width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
-                mTimestampOffset, streamSetId);
+                mTimestampOffset, physicalCameraId, streamSetId);
     } else if (isShared) {
         newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
                 width, height, format, consumerUsage, dataSpace, rotation,
-                mTimestampOffset, streamSetId);
+                mTimestampOffset, physicalCameraId, streamSetId);
     } else if (consumers.size() == 0 && hasDeferredConsumer) {
         newStream = new Camera3OutputStream(mNextStreamId,
                 width, height, format, consumerUsage, dataSpace, rotation,
-                mTimestampOffset, streamSetId);
+                mTimestampOffset, physicalCameraId, streamSetId);
     } else {
         newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
                 width, height, format, dataSpace, rotation,
-                mTimestampOffset, streamSetId);
+                mTimestampOffset, physicalCameraId, streamSetId);
     }
 
     size_t consumerCount = consumers.size();
@@ -1508,11 +1522,20 @@
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
+    return filterParamsAndConfigureLocked(sessionParams, operatingMode);
+}
+
+status_t Camera3Device::filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
+        int operatingMode) {
     //Filter out any incoming session parameters
     const CameraMetadata params(sessionParams);
-    CameraMetadata filteredParams;
     camera_metadata_entry_t availableSessionKeys = mDeviceInfo.find(
             ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
+    CameraMetadata filteredParams(availableSessionKeys.count);
+    camera_metadata_t *meta = const_cast<camera_metadata_t *>(
+            filteredParams.getAndLock());
+    set_camera_metadata_vendor_id(meta, mVendorTagId);
+    filteredParams.unlock(meta);
     if (availableSessionKeys.count > 0) {
         for (size_t i = 0; i < availableSessionKeys.count; i++) {
             camera_metadata_ro_entry entry = params.find(
@@ -2075,15 +2098,15 @@
  */
 
 sp<Camera3Device::CaptureRequest> Camera3Device::createCaptureRequest(
-        const CameraMetadata &request, const SurfaceMap &surfaceMap) {
+        const PhysicalCameraSettingsList &request, const SurfaceMap &surfaceMap) {
     ATRACE_CALL();
     status_t res;
 
     sp<CaptureRequest> newRequest = new CaptureRequest;
-    newRequest->mSettings = request;
+    newRequest->mSettingsList = request;
 
     camera_metadata_entry_t inputStreams =
-            newRequest->mSettings.find(ANDROID_REQUEST_INPUT_STREAMS);
+            newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_INPUT_STREAMS);
     if (inputStreams.count > 0) {
         if (mInputStream == NULL ||
                 mInputStream->getId() != inputStreams.data.i32[0]) {
@@ -2109,11 +2132,11 @@
         }
 
         newRequest->mInputStream = mInputStream;
-        newRequest->mSettings.erase(ANDROID_REQUEST_INPUT_STREAMS);
+        newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_INPUT_STREAMS);
     }
 
     camera_metadata_entry_t streams =
-            newRequest->mSettings.find(ANDROID_REQUEST_OUTPUT_STREAMS);
+            newRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_OUTPUT_STREAMS);
     if (streams.count == 0) {
         CLOGE("Zero output streams specified!");
         return NULL;
@@ -2161,7 +2184,7 @@
 
         newRequest->mOutputStreams.push(stream);
     }
-    newRequest->mSettings.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
+    newRequest->mSettingsList.begin()->metadata.erase(ANDROID_REQUEST_OUTPUT_STREAMS);
     newRequest->mBatchSize = 1;
 
     return newRequest;
@@ -2203,10 +2226,47 @@
     // properly clean things up
     internalUpdateStatusLocked(STATUS_UNCONFIGURED);
     mNeedConfig = true;
+
+    res = mPreparerThread->resume();
+    if (res != OK) {
+        ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
+    }
+}
+
+bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams) {
+    ATRACE_CALL();
+    bool ret = false;
+
+    Mutex::Autolock il(mInterfaceLock);
+    nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
+
+    Mutex::Autolock l(mLock);
+    auto rc = internalPauseAndWaitLocked(maxExpectedDuration);
+    if (rc == NO_ERROR) {
+        mNeedConfig = true;
+        rc = configureStreamsLocked(mOperatingMode, sessionParams, /*notifyRequestThread*/ false);
+        if (rc == NO_ERROR) {
+            ret = true;
+            mPauseStateNotify = false;
+            //Moving to active state while holding 'mLock' is important.
+            //There could be pending calls to 'create-/deleteStream' which
+            //will trigger another stream configuration while the already
+            //present streams end up with outstanding buffers that will
+            //not get drained.
+            internalUpdateStatusLocked(STATUS_ACTIVE);
+        } else {
+            setErrorStateLocked("%s: Failed to re-configure camera: %d",
+                    __FUNCTION__, rc);
+        }
+    } else {
+        ALOGE("%s: Failed to pause streaming: %d", __FUNCTION__, rc);
+    }
+
+    return ret;
 }
 
 status_t Camera3Device::configureStreamsLocked(int operatingMode,
-        const CameraMetadata& sessionParams) {
+        const CameraMetadata& sessionParams, bool notifyRequestThread) {
     ATRACE_CALL();
     status_t res;
 
@@ -2247,6 +2307,8 @@
     // Start configuring the streams
     ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
 
+    mPreparerThread->pause();
+
     camera3_stream_configuration config;
     config.operation_mode = mOperatingMode;
     config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
@@ -2338,7 +2400,9 @@
 
     // Request thread needs to know to avoid using repeat-last-settings protocol
     // across configure_streams() calls
-    mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration);
+    if (notifyRequestThread) {
+        mRequestThread->configurationComplete(mIsConstrainedHighSpeedConfiguration, sessionParams);
+    }
 
     char value[PROPERTY_VALUE_MAX];
     property_get("camera.fifo.disable", value, "0");
@@ -2376,6 +2440,12 @@
     // tear down the deleted streams after configure streams.
     mDeletedStreams.clear();
 
+    auto rc = mPreparerThread->resume();
+    if (rc != OK) {
+        SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
+        return rc;
+    }
+
     return OK;
 }
 
@@ -3260,10 +3330,13 @@
 
     // Convert stream config to HIDL
     std::set<int> activeStreams;
-    device::V3_4::StreamConfiguration requestedConfiguration;
-    requestedConfiguration.v3_2.streams.resize(config->num_streams);
+    device::V3_2::StreamConfiguration requestedConfiguration3_2;
+    device::V3_4::StreamConfiguration requestedConfiguration3_4;
+    requestedConfiguration3_2.streams.resize(config->num_streams);
+    requestedConfiguration3_4.streams.resize(config->num_streams);
     for (size_t i = 0; i < config->num_streams; i++) {
-        Stream &dst = requestedConfiguration.v3_2.streams[i];
+        device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
+        device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
         camera3_stream_t *src = config->streams[i];
 
         Camera3Stream* cam3stream = Camera3Stream::cast(src);
@@ -3282,14 +3355,18 @@
                         __FUNCTION__, streamId, config->streams[i]->stream_type);
                 return BAD_VALUE;
         }
-        dst.id = streamId;
-        dst.streamType = streamType;
-        dst.width = src->width;
-        dst.height = src->height;
-        dst.format = mapToPixelFormat(src->format);
-        dst.usage = mapToConsumerUsage(cam3stream->getUsage());
-        dst.dataSpace = mapToHidlDataspace(src->data_space);
-        dst.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+        dst3_2.id = streamId;
+        dst3_2.streamType = streamType;
+        dst3_2.width = src->width;
+        dst3_2.height = src->height;
+        dst3_2.format = mapToPixelFormat(src->format);
+        dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
+        dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
+        dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+        dst3_4.v3_2 = dst3_2;
+        if (src->physical_camera_id != nullptr) {
+            dst3_4.physicalCameraId = src->physical_camera_id;
+        }
 
         activeStreams.insert(streamId);
         // Create Buffer ID map if necessary
@@ -3308,19 +3385,20 @@
         }
     }
 
+    StreamConfigurationMode operationMode;
     res = mapToStreamConfigurationMode(
             (camera3_stream_configuration_mode_t) config->operation_mode,
-            /*out*/ &requestedConfiguration.v3_2.operationMode);
+            /*out*/ &operationMode);
     if (res != OK) {
         return res;
     }
-
-    requestedConfiguration.sessionParams.setToExternal(
+    requestedConfiguration3_2.operationMode = operationMode;
+    requestedConfiguration3_4.operationMode = operationMode;
+    requestedConfiguration3_4.sessionParams.setToExternal(
             reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
             get_camera_metadata_size(sessionParams));
 
     // Invoke configureStreams
-
     device::V3_3::HalStreamConfiguration finalConfiguration;
     common::V1_0::Status status;
 
@@ -3338,22 +3416,28 @@
     }
 
     if (hidlSession_3_4 != nullptr) {
-        // We do; use v3.4 for the call
+        // We do; use v3.4 for the call, and construct a v3.4
+        // HalStreamConfiguration
         ALOGV("%s: v3.4 device found", __FUNCTION__);
-        auto err = hidlSession_3_4->configureStreams_3_4(requestedConfiguration,
-            [&status, &finalConfiguration]
-            (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
-                finalConfiguration = halConfiguration;
+        device::V3_4::HalStreamConfiguration finalConfiguration3_4;
+        auto err = hidlSession_3_4->configureStreams_3_4(requestedConfiguration3_4,
+            [&status, &finalConfiguration3_4]
+            (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
+                finalConfiguration3_4 = halConfiguration;
                 status = s;
             });
         if (!err.isOk()) {
             ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
             return DEAD_OBJECT;
         }
+        finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
+        for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
+            finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
+        }
     } else if (hidlSession_3_3 != nullptr) {
         // We do; use v3.3 for the call
         ALOGV("%s: v3.3 device found", __FUNCTION__);
-        auto err = hidlSession_3_3->configureStreams_3_3(requestedConfiguration.v3_2,
+        auto err = hidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
             [&status, &finalConfiguration]
             (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
                 finalConfiguration = halConfiguration;
@@ -3367,7 +3451,7 @@
         // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
         ALOGV("%s: v3.2 device found", __FUNCTION__);
         HalStreamConfiguration finalConfiguration_3_2;
-        auto err = mHidlSession->configureStreams(requestedConfiguration.v3_2,
+        auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
                 [&status, &finalConfiguration_3_2]
                 (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
                     finalConfiguration_3_2 = halConfiguration;
@@ -3381,7 +3465,7 @@
         for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
             finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
             finalConfiguration.streams[i].overrideDataSpace =
-                    requestedConfiguration.v3_2.streams[i].dataSpace;
+                    requestedConfiguration3_2.streams[i].dataSpace;
         }
     }
 
@@ -3535,13 +3619,29 @@
     ATRACE_NAME("CameraHal::processBatchCaptureRequests");
     if (!valid()) return INVALID_OPERATION;
 
+    sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
+    auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
+    if (castResult_3_4.isOk()) {
+        hidlSession_3_4 = castResult_3_4;
+    }
+
     hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
+    hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
     size_t batchSize = requests.size();
-    captureRequests.resize(batchSize);
+    if (hidlSession_3_4 != nullptr) {
+        captureRequests_3_4.resize(batchSize);
+    } else {
+        captureRequests.resize(batchSize);
+    }
     std::vector<native_handle_t*> handlesCreated;
 
     for (size_t i = 0; i < batchSize; i++) {
-        wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i], /*out*/&handlesCreated);
+        if (hidlSession_3_4 != nullptr) {
+            wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
+                    /*out*/&handlesCreated);
+        } else {
+            wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i], /*out*/&handlesCreated);
+        }
     }
 
     std::vector<device::V3_2::BufferCache> cachesToRemove;
@@ -3562,7 +3662,12 @@
     // Write metadata to FMQ.
     for (size_t i = 0; i < batchSize; i++) {
         camera3_capture_request_t* request = requests[i];
-        device::V3_2::CaptureRequest* captureRequest = &captureRequests[i];
+        device::V3_2::CaptureRequest* captureRequest;
+        if (hidlSession_3_4 != nullptr) {
+            captureRequest = &captureRequests_3_4[i].v3_2;
+        } else {
+            captureRequest = &captureRequests[i];
+        }
 
         if (request->settings != nullptr) {
             size_t settingsSize = get_camera_metadata_size(request->settings);
@@ -3584,12 +3689,46 @@
             captureRequest->settings.resize(0);
             captureRequest->fmqSettingsSize = 0u;
         }
+
+        if (hidlSession_3_4 != nullptr) {
+            captureRequests_3_4[i].physicalCameraSettings.resize(request->num_physcam_settings);
+            for (size_t j = 0; j < request->num_physcam_settings; j++) {
+                size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
+                if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
+                            reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
+                            settingsSize)) {
+                    captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
+                    captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = settingsSize;
+                } else {
+                    if (mRequestMetadataQueue != nullptr) {
+                        ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
+                    }
+                    captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
+                            reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
+                                    request->physcam_settings[j])),
+                            get_camera_metadata_size(request->physcam_settings[j]));
+                    captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
+                }
+                captureRequests_3_4[i].physicalCameraSettings[j].physicalCameraId =
+                    request->physcam_id[j];
+            }
+        }
     }
-    auto err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
+
+    hardware::details::return_status err;
+    if (hidlSession_3_4 != nullptr) {
+        err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
             [&status, &numRequestProcessed] (auto s, uint32_t n) {
                 status = s;
                 *numRequestProcessed = n;
             });
+    } else {
+        err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
+            [&status, &numRequestProcessed] (auto s, uint32_t n) {
+                status = s;
+                *numRequestProcessed = n;
+            });
+    }
     if (!err.isOk()) {
         ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
         return DEAD_OBJECT;
@@ -3747,7 +3886,7 @@
 
 Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
         sp<StatusTracker> statusTracker,
-        sp<HalInterface> interface) :
+        sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys) :
         Thread(/*canCallJava*/false),
         mParent(parent),
         mStatusTracker(statusTracker),
@@ -3764,7 +3903,9 @@
         mRepeatingLastFrameNumber(
             hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
         mPrepareVideoStream(false),
-        mRequestLatency(kRequestLatencyBinSize) {
+        mRequestLatency(kRequestLatencyBinSize),
+        mSessionParamKeys(sessionParamKeys),
+        mLatestSessionParams(sessionParamKeys.size()) {
     mStatusId = statusTracker->addComponent();
 }
 
@@ -3777,10 +3918,12 @@
     mListener = listener;
 }
 
-void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed) {
+void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed,
+        const CameraMetadata& sessionParams) {
     ATRACE_CALL();
     Mutex::Autolock l(mRequestLock);
     mReconfigured = true;
+    mLatestSessionParams = sessionParams;
     // Prepare video stream for high speed recording.
     mPrepareVideoStream = isConstrainedHighSpeed;
 }
@@ -4068,9 +4211,12 @@
         }
 
         if (nextRequest.halRequest.settings != NULL) {
-            nextRequest.captureRequest->mSettings.unlock(nextRequest.halRequest.settings);
+            nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
+                    nextRequest.halRequest.settings);
         }
 
+        cleanupPhysicalSettings(nextRequest.captureRequest, &nextRequest.halRequest);
+
         if (!triggerRemoveFailed) {
             // Remove any previously queued triggers (after unlock)
             status_t removeTriggerRes = removeTriggers(mPrevRequest);
@@ -4139,9 +4285,12 @@
         }
 
         if (nextRequest.halRequest.settings != NULL) {
-            nextRequest.captureRequest->mSettings.unlock(nextRequest.halRequest.settings);
+            nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
+                    nextRequest.halRequest.settings);
         }
 
+        cleanupPhysicalSettings(nextRequest.captureRequest, &nextRequest.halRequest);
+
         // Remove any previously queued triggers (after unlock)
         res = removeTriggers(mPrevRequest);
         if (res != OK) {
@@ -4191,6 +4340,52 @@
     return maxExpectedDuration;
 }
 
+bool Camera3Device::RequestThread::updateSessionParameters(const CameraMetadata& settings) {
+    ATRACE_CALL();
+    bool updatesDetected = false;
+
+    for (auto tag : mSessionParamKeys) {
+        camera_metadata_ro_entry entry = settings.find(tag);
+        camera_metadata_entry lastEntry = mLatestSessionParams.find(tag);
+
+        if (entry.count > 0) {
+            bool isDifferent = false;
+            if (lastEntry.count > 0) {
+                // Have a last value, compare to see if changed
+                if (lastEntry.type == entry.type &&
+                        lastEntry.count == entry.count) {
+                    // Same type and count, compare values
+                    size_t bytesPerValue = camera_metadata_type_size[lastEntry.type];
+                    size_t entryBytes = bytesPerValue * lastEntry.count;
+                    int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes);
+                    if (cmp != 0) {
+                        isDifferent = true;
+                    }
+                } else {
+                    // Count or type has changed
+                    isDifferent = true;
+                }
+            } else {
+                // No last entry, so always consider to be different
+                isDifferent = true;
+            }
+
+            if (isDifferent) {
+                ALOGV("%s: Session parameter tag id %d changed", __FUNCTION__, tag);
+                mLatestSessionParams.update(entry);
+                updatesDetected = true;
+            }
+        } else if (lastEntry.count > 0) {
+            // Value has been removed
+            ALOGV("%s: Session parameter tag id %d removed", __FUNCTION__, tag);
+            mLatestSessionParams.erase(tag);
+            updatesDetected = true;
+        }
+    }
+
+    return updatesDetected;
+}
+
 bool Camera3Device::RequestThread::threadLoop() {
     ATRACE_CALL();
     status_t res;
@@ -4209,7 +4404,7 @@
     // Get the latest request ID, if any
     int latestRequestId;
     camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1].
-            captureRequest->mSettings.find(ANDROID_REQUEST_ID);
+            captureRequest->mSettingsList.begin()->metadata.find(ANDROID_REQUEST_ID);
     if (requestIdEntry.count > 0) {
         latestRequestId = requestIdEntry.data.i32[0];
     } else {
@@ -4217,6 +4412,49 @@
         latestRequestId = NAME_NOT_FOUND;
     }
 
+    // 'mNextRequests' will at this point contain either a set of HFR batched requests
+    //  or a single request from streaming or burst. In either case the first element
+    //  should contain the latest camera settings that we need to check for any session
+    //  parameter updates.
+    if (updateSessionParameters(mNextRequests[0].captureRequest->mSettingsList.begin()->metadata)) {
+        res = OK;
+
+        //Input stream buffers are already acquired at this point so an input stream
+        //will not be able to move to idle state unless we force it.
+        if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
+            res = mNextRequests[0].captureRequest->mInputStream->forceToIdle();
+            if (res != OK) {
+                ALOGE("%s: Failed to force idle input stream: %d", __FUNCTION__, res);
+                cleanUpFailedRequests(/*sendRequestError*/ false);
+                return false;
+            }
+        }
+
+        if (res == OK) {
+            sp<StatusTracker> statusTracker = mStatusTracker.promote();
+            if (statusTracker != 0) {
+                statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
+
+                sp<Camera3Device> parent = mParent.promote();
+                if (parent != nullptr) {
+                    mReconfigured |= parent->reconfigureCamera(mLatestSessionParams);
+                }
+
+                statusTracker->markComponentActive(mStatusId);
+                setPaused(false);
+            }
+
+            if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
+                mNextRequests[0].captureRequest->mInputStream->restoreConfiguredState();
+                if (res != OK) {
+                    ALOGE("%s: Failed to restore configured input stream: %d", __FUNCTION__, res);
+                    cleanUpFailedRequests(/*sendRequestError*/ false);
+                    return false;
+                }
+            }
+        }
+    }
+
     // Prepare a batch of HAL requests and output buffers.
     res = prepareHalRequests();
     if (res == TIMED_OUT) {
@@ -4320,8 +4558,8 @@
              * The request should be presorted so accesses in HAL
              *   are O(logn). Sidenote, sorting a sorted metadata is nop.
              */
-            captureRequest->mSettings.sort();
-            halRequest->settings = captureRequest->mSettings.getAndLock();
+            captureRequest->mSettingsList.begin()->metadata.sort();
+            halRequest->settings = captureRequest->mSettingsList.begin()->metadata.getAndLock();
             mPrevRequest = captureRequest;
             ALOGVV("%s: Request settings are NEW", __FUNCTION__);
 
@@ -4345,6 +4583,20 @@
                    __FUNCTION__);
         }
 
+        if (captureRequest->mSettingsList.size() > 1) {
+            halRequest->num_physcam_settings = captureRequest->mSettingsList.size() - 1;
+            halRequest->physcam_id = new const char* [halRequest->num_physcam_settings];
+            halRequest->physcam_settings =
+                new const camera_metadata* [halRequest->num_physcam_settings];
+            auto it = ++captureRequest->mSettingsList.begin();
+            size_t i = 0;
+            for (; it != captureRequest->mSettingsList.end(); it++, i++) {
+                halRequest->physcam_id[i] = it->cameraId.c_str();
+                it->metadata.sort();
+                halRequest->physcam_settings[i] = it->metadata.getAndLock();
+            }
+        }
+
         uint32_t totalNumBuffers = 0;
 
         // Fill in buffers
@@ -4515,6 +4767,30 @@
             mExpectedInflightDuration : kMinInflightDuration;
 }
 
+void Camera3Device::RequestThread::cleanupPhysicalSettings(sp<CaptureRequest> request,
+        camera3_capture_request_t *halRequest) {
+    if ((request == nullptr) || (halRequest == nullptr)) {
+        ALOGE("%s: Invalid request!", __FUNCTION__);
+        return;
+    }
+
+    if (halRequest->num_physcam_settings > 0) {
+        if (halRequest->physcam_id != nullptr) {
+            delete [] halRequest->physcam_id;
+            halRequest->physcam_id = nullptr;
+        }
+        if (halRequest->physcam_settings != nullptr) {
+            auto it = ++(request->mSettingsList.begin());
+            size_t i = 0;
+            for (; it != request->mSettingsList.end(); it++, i++) {
+                it->metadata.unlock(halRequest->physcam_settings[i]);
+            }
+            delete [] halRequest->physcam_settings;
+            halRequest->physcam_settings = nullptr;
+        }
+    }
+}
+
 void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) {
     if (mNextRequests.empty()) {
         return;
@@ -4531,9 +4807,11 @@
         Vector<camera3_stream_buffer_t>* outputBuffers = &nextRequest.outputBuffers;
 
         if (halRequest->settings != NULL) {
-            captureRequest->mSettings.unlock(halRequest->settings);
+            captureRequest->mSettingsList.begin()->metadata.unlock(halRequest->settings);
         }
 
+        cleanupPhysicalSettings(captureRequest, halRequest);
+
         if (captureRequest->mInputStream != NULL) {
             captureRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
             captureRequest->mInputStream->returnInputBuffer(captureRequest->mInputBuffer);
@@ -4797,7 +5075,7 @@
         return DEAD_OBJECT;
     }
 
-    CameraMetadata &metadata = request->mSettings;
+    CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
     size_t count = mTriggerMap.size();
 
     for (size_t i = 0; i < count; ++i) {
@@ -4880,7 +5158,7 @@
     ATRACE_CALL();
     Mutex::Autolock al(mTriggerMutex);
 
-    CameraMetadata &metadata = request->mSettings;
+    CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
 
     /**
      * Replace all old entries with their old values.
@@ -4945,7 +5223,7 @@
     static const int32_t dummyTriggerId = 1;
     status_t res;
 
-    CameraMetadata &metadata = request->mSettings;
+    CameraMetadata &metadata = request->mSettingsList.begin()->metadata;
 
     // If AF trigger is active, insert a dummy AF trigger ID if none already
     // exists
@@ -4980,7 +5258,7 @@
 
 Camera3Device::PreparerThread::PreparerThread() :
         Thread(/*canCallJava*/false), mListener(nullptr),
-        mActive(false), mCancelNow(false) {
+        mActive(false), mCancelNow(false), mCurrentMaxCount(0), mCurrentPrepareComplete(false) {
 }
 
 Camera3Device::PreparerThread::~PreparerThread() {
@@ -5031,18 +5309,101 @@
     }
 
     // queue up the work
-    mPendingStreams.push_back(stream);
+    mPendingStreams.emplace(maxCount, stream);
     ALOGV("%s: Stream %d queued for preparing", __FUNCTION__, stream->getId());
 
     return OK;
 }
 
+void Camera3Device::PreparerThread::pause() {
+    ATRACE_CALL();
+
+    Mutex::Autolock l(mLock);
+
+    std::unordered_map<int, sp<camera3::Camera3StreamInterface> > pendingStreams;
+    pendingStreams.insert(mPendingStreams.begin(), mPendingStreams.end());
+    sp<camera3::Camera3StreamInterface> currentStream = mCurrentStream;
+    int currentMaxCount = mCurrentMaxCount;
+    mPendingStreams.clear();
+    mCancelNow = true;
+    while (mActive) {
+        auto res = mThreadActiveSignal.waitRelative(mLock, kActiveTimeout);
+        if (res == TIMED_OUT) {
+            ALOGE("%s: Timed out waiting on prepare thread!", __FUNCTION__);
+            return;
+        } else if (res != OK) {
+            ALOGE("%s: Encountered an error: %d waiting on prepare thread!", __FUNCTION__, res);
+            return;
+        }
+    }
+
+    //Check whether the prepare thread was able to complete the current
+    //stream. In case work is still pending emplace it along with the rest
+    //of the streams in the pending list.
+    if (currentStream != nullptr) {
+        if (!mCurrentPrepareComplete) {
+            pendingStreams.emplace(currentMaxCount, currentStream);
+        }
+    }
+
+    mPendingStreams.insert(pendingStreams.begin(), pendingStreams.end());
+    for (const auto& it : mPendingStreams) {
+        it.second->cancelPrepare();
+    }
+}
+
+status_t Camera3Device::PreparerThread::resume() {
+    ATRACE_CALL();
+    status_t res;
+
+    Mutex::Autolock l(mLock);
+    sp<NotificationListener> listener = mListener.promote();
+
+    if (mActive) {
+        ALOGE("%s: Trying to resume an already active prepare thread!", __FUNCTION__);
+        return NO_INIT;
+    }
+
+    auto it = mPendingStreams.begin();
+    for (; it != mPendingStreams.end();) {
+        res = it->second->startPrepare(it->first);
+        if (res == OK) {
+            if (listener != NULL) {
+                listener->notifyPrepared(it->second->getId());
+            }
+            it = mPendingStreams.erase(it);
+        } else if (res != NOT_ENOUGH_DATA) {
+            ALOGE("%s: Unable to start preparer stream: %d (%s)", __FUNCTION__,
+                    res, strerror(-res));
+            it = mPendingStreams.erase(it);
+        } else {
+            it++;
+        }
+    }
+
+    if (mPendingStreams.empty()) {
+        return OK;
+    }
+
+    res = Thread::run("C3PrepThread", PRIORITY_BACKGROUND);
+    if (res != OK) {
+        ALOGE("%s: Unable to start preparer stream: %d (%s)",
+                __FUNCTION__, res, strerror(-res));
+        return res;
+    }
+    mCancelNow = false;
+    mActive = true;
+    ALOGV("%s: Preparer stream started", __FUNCTION__);
+
+    return OK;
+}
+
 status_t Camera3Device::PreparerThread::clear() {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
 
-    for (const auto& stream : mPendingStreams) {
-        stream->cancelPrepare();
+    for (const auto& it : mPendingStreams) {
+        it.second->cancelPrepare();
     }
     mPendingStreams.clear();
     mCancelNow = true;
@@ -5067,12 +5428,15 @@
                 // threadLoop _must not_ re-acquire mLock after it sets mActive to false; would
                 // cause deadlock with prepare()'s requestExitAndWait triggered by !mActive.
                 mActive = false;
+                mThreadActiveSignal.signal();
                 return false;
             }
 
             // Get next stream to prepare
             auto it = mPendingStreams.begin();
-            mCurrentStream = *it;
+            mCurrentStream = it->second;
+            mCurrentMaxCount = it->first;
+            mCurrentPrepareComplete = false;
             mPendingStreams.erase(it);
             ATRACE_ASYNC_BEGIN("stream prepare", mCurrentStream->getId());
             ALOGV("%s: Preparing stream %d", __FUNCTION__, mCurrentStream->getId());
@@ -5107,6 +5471,7 @@
 
     ATRACE_ASYNC_END("stream prepare", mCurrentStream->getId());
     mCurrentStream.clear();
+    mCurrentPrepareComplete = true;
 
     return true;
 }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index cc7eb35..63e6219 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -99,12 +99,12 @@
     // Capture and setStreamingRequest will configure streams if currently in
     // idle state
     status_t capture(CameraMetadata &request, int64_t *lastFrameNumber = NULL) override;
-    status_t captureList(const List<const CameraMetadata> &requests,
+    status_t captureList(const List<const PhysicalCameraSettingsList> &requestsList,
             const std::list<const SurfaceMap> &surfaceMaps,
             int64_t *lastFrameNumber = NULL) override;
     status_t setStreamingRequest(const CameraMetadata &request,
             int64_t *lastFrameNumber = NULL) override;
-    status_t setStreamingRequestList(const List<const CameraMetadata> &requests,
+    status_t setStreamingRequestList(const List<const PhysicalCameraSettingsList> &requestsList,
             const std::list<const SurfaceMap> &surfaceMaps,
             int64_t *lastFrameNumber = NULL) override;
     status_t clearStreamingRequest(int64_t *lastFrameNumber = NULL) override;
@@ -119,12 +119,14 @@
     status_t createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+            const String8& physicalCameraId,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
             bool isShared = false, uint64_t consumerUsage = 0) override;
     status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation, int *id,
+            const String8& physicalCameraId,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
             bool isShared = false, uint64_t consumerUsage = 0) override;
@@ -426,7 +428,7 @@
 
     class CaptureRequest : public LightRefBase<CaptureRequest> {
       public:
-        CameraMetadata                      mSettings;
+        PhysicalCameraSettingsList          mSettingsList;
         sp<camera3::Camera3Stream>          mInputStream;
         camera3_stream_buffer_t             mInputBuffer;
         Vector<sp<camera3::Camera3OutputStreamInterface> >
@@ -446,17 +448,17 @@
     status_t checkStatusOkToCaptureLocked();
 
     status_t convertMetadataListToRequestListLocked(
-            const List<const CameraMetadata> &metadataList,
+            const List<const PhysicalCameraSettingsList> &metadataList,
             const std::list<const SurfaceMap> &surfaceMaps,
             bool repeating,
             /*out*/
             RequestList *requestList);
 
-    void convertToRequestList(List<const CameraMetadata>& requests,
+    void convertToRequestList(List<const PhysicalCameraSettingsList>& requestsList,
             std::list<const SurfaceMap>& surfaceMaps,
             const CameraMetadata& request);
 
-    status_t submitRequestsHelper(const List<const CameraMetadata> &requests,
+    status_t submitRequestsHelper(const List<const PhysicalCameraSettingsList> &requestsList,
                                   const std::list<const SurfaceMap> &surfaceMaps,
                                   bool repeating,
                                   int64_t *lastFrameNumber = NULL);
@@ -541,22 +543,34 @@
      * Do common work for setting up a streaming or single capture request.
      * On success, will transition to ACTIVE if in IDLE.
      */
-    sp<CaptureRequest> setUpRequestLocked(const CameraMetadata &request,
+    sp<CaptureRequest> setUpRequestLocked(const PhysicalCameraSettingsList &request,
                                           const SurfaceMap &surfaceMap);
 
     /**
      * Build a CaptureRequest request from the CameraDeviceBase request
      * settings.
      */
-    sp<CaptureRequest> createCaptureRequest(const CameraMetadata &request,
+    sp<CaptureRequest> createCaptureRequest(const PhysicalCameraSettingsList &request,
                                             const SurfaceMap &surfaceMap);
 
     /**
+     * Internally re-configure camera device using new session parameters.
+     * This will get triggered by the request thread.
+     */
+    bool reconfigureCamera(const CameraMetadata& sessionParams);
+
+    /**
+     * Filter stream session parameters and configure camera HAL.
+     */
+    status_t filterParamsAndConfigureLocked(const CameraMetadata& sessionParams,
+            int operatingMode);
+
+    /**
      * Take the currently-defined set of streams and configure the HAL to use
      * them. This is a long-running operation (may be several hundered ms).
      */
     status_t           configureStreamsLocked(int operatingMode,
-            const CameraMetadata& sessionParams);
+            const CameraMetadata& sessionParams, bool notifyRequestThread = true);
 
     /**
      * Cancel stream configuration that did not finish successfully.
@@ -655,7 +669,7 @@
 
         RequestThread(wp<Camera3Device> parent,
                 sp<camera3::StatusTracker> statusTracker,
-                sp<HalInterface> interface);
+                sp<HalInterface> interface, const Vector<int32_t>& sessionParamKeys);
         ~RequestThread();
 
         void     setNotificationListener(wp<NotificationListener> listener);
@@ -663,7 +677,8 @@
         /**
          * Call after stream (re)-configuration is completed.
          */
-        void     configurationComplete(bool isConstrainedHighSpeed);
+        void     configurationComplete(bool isConstrainedHighSpeed,
+                const CameraMetadata& sessionParams);
 
         /**
          * Set or clear the list of repeating requests. Does not block
@@ -790,6 +805,10 @@
         // Stop the repeating request if any of its output streams is abandoned.
         void checkAndStopRepeatingRequest();
 
+        // Release physical camera settings and camera id resources.
+        void cleanupPhysicalSettings(sp<CaptureRequest> request,
+                /*out*/camera3_capture_request_t *halRequest);
+
         // Pause handling
         bool               waitIfPaused();
         void               unpauseForNewRequests();
@@ -812,6 +831,12 @@
         // Calculate the expected maximum duration for a request
         nsecs_t calculateMaxExpectedDuration(const camera_metadata_t *request);
 
+        // Check and update latest session parameters based on the current request settings.
+        bool updateSessionParameters(const CameraMetadata& settings);
+
+        // Re-configure camera using the latest session parameters.
+        bool reconfigureCamera();
+
         wp<Camera3Device>  mParent;
         wp<camera3::StatusTracker>  mStatusTracker;
         sp<HalInterface>   mInterface;
@@ -869,6 +894,9 @@
 
         static const int32_t kRequestLatencyBinSize = 40; // in ms
         CameraLatencyHistogram mRequestLatency;
+
+        Vector<int32_t>    mSessionParamKeys;
+        CameraMetadata     mLatestSessionParams;
     };
     sp<RequestThread> mRequestThread;
 
@@ -1006,21 +1034,34 @@
          */
         status_t clear();
 
+        /**
+         * Pause all preparation activities
+         */
+        void pause();
+
+        /**
+         * Resume preparation activities
+         */
+        status_t resume();
+
       private:
         Mutex mLock;
+        Condition mThreadActiveSignal;
 
         virtual bool threadLoop();
 
         // Guarded by mLock
 
         wp<NotificationListener> mListener;
-        List<sp<camera3::Camera3StreamInterface> > mPendingStreams;
+        std::unordered_map<int, sp<camera3::Camera3StreamInterface> > mPendingStreams;
         bool mActive;
         bool mCancelNow;
 
         // Only accessed by threadLoop and the destructor
 
         sp<camera3::Camera3StreamInterface> mCurrentStream;
+        int mCurrentMaxCount;
+        bool mCurrentPrepareComplete;
     };
     sp<PreparerThread> mPreparerThread;
 
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 0a245c4..44eb68a 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2014-2018 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.
@@ -26,9 +26,12 @@
 
 namespace camera3 {
 
+const String8 Camera3DummyStream::DUMMY_ID;
+
 Camera3DummyStream::Camera3DummyStream(int id) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, DUMMY_WIDTH, DUMMY_HEIGHT,
-                /*maxSize*/0, DUMMY_FORMAT, DUMMY_DATASPACE, DUMMY_ROTATION) {
+                /*maxSize*/0, DUMMY_FORMAT, DUMMY_DATASPACE, DUMMY_ROTATION,
+                DUMMY_ID) {
 
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 684f4b0..dcf9160 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2014-2018 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.
@@ -114,6 +114,7 @@
     static const android_dataspace DUMMY_DATASPACE = HAL_DATASPACE_UNKNOWN;
     static const camera3_stream_rotation_t DUMMY_ROTATION = CAMERA3_STREAM_ROTATION_0;
     static const uint64_t DUMMY_USAGE = GRALLOC_USAGE_HW_COMPOSER;
+    static const String8 DUMMY_ID;
 
     /**
      * Internal Camera3Stream interface
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index a52422d..3c1e43d 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -31,9 +31,11 @@
 
 Camera3IOStreamBase::Camera3IOStreamBase(int id, camera3_stream_type_t type,
         uint32_t width, uint32_t height, size_t maxSize, int format,
-        android_dataspace dataSpace, camera3_stream_rotation_t rotation, int setId) :
+        android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+        const String8& physicalCameraId, int setId) :
         Camera3Stream(id, type,
-                width, height, maxSize, format, dataSpace, rotation, setId),
+                width, height, maxSize, format, dataSpace, rotation,
+                physicalCameraId, setId),
         mTotalBufferCount(0),
         mHandoutTotalBufferCount(0),
         mHandoutOutputBufferCount(0),
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index 2376058..0a31d44 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -35,6 +35,7 @@
     Camera3IOStreamBase(int id, camera3_stream_type_t type,
             uint32_t width, uint32_t height, size_t maxSize, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+            const String8& physicalCameraId,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
   public:
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 2cb1ea7..017d7be 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -27,10 +27,13 @@
 
 namespace camera3 {
 
+const String8 Camera3InputStream::DUMMY_ID;
+
 Camera3InputStream::Camera3InputStream(int id,
         uint32_t width, uint32_t height, int format) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_INPUT, width, height, /*maxSize*/0,
-                            format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0) {
+                            format, HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0,
+                            DUMMY_ID) {
 
     if (format == HAL_PIXEL_FORMAT_BLOB) {
         ALOGE("%s: Bad format, BLOB not supported", __FUNCTION__);
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 81226f8..0732464 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -53,6 +53,8 @@
     sp<IGraphicBufferProducer> mProducer;
     Vector<BufferItem> mBuffersInFlight;
 
+    static const String8 DUMMY_ID;
+
     /**
      * Camera3IOStreamBase
      */
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index e79eecc..b73e256 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -35,9 +35,11 @@
         sp<Surface> consumer,
         uint32_t width, uint32_t height, int format,
         android_dataspace dataSpace, camera3_stream_rotation_t rotation,
-        nsecs_t timestampOffset, int setId) :
+        nsecs_t timestampOffset, const String8& physicalCameraId,
+        int setId) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
-                            /*maxSize*/0, format, dataSpace, rotation, setId),
+                            /*maxSize*/0, format, dataSpace, rotation,
+                            physicalCameraId, setId),
         mConsumer(consumer),
         mTransform(0),
         mTraceFirstBuffer(true),
@@ -61,9 +63,9 @@
         sp<Surface> consumer,
         uint32_t width, uint32_t height, size_t maxSize, int format,
         android_dataspace dataSpace, camera3_stream_rotation_t rotation,
-        nsecs_t timestampOffset, int setId) :
+        nsecs_t timestampOffset, const String8& physicalCameraId, int setId) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height, maxSize,
-                            format, dataSpace, rotation, setId),
+                            format, dataSpace, rotation, physicalCameraId, setId),
         mConsumer(consumer),
         mTransform(0),
         mTraceFirstBuffer(true),
@@ -93,9 +95,11 @@
 Camera3OutputStream::Camera3OutputStream(int id,
         uint32_t width, uint32_t height, int format,
         uint64_t consumerUsage, android_dataspace dataSpace,
-        camera3_stream_rotation_t rotation, nsecs_t timestampOffset, int setId) :
+        camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+        const String8& physicalCameraId, int setId) :
         Camera3IOStreamBase(id, CAMERA3_STREAM_OUTPUT, width, height,
-                            /*maxSize*/0, format, dataSpace, rotation, setId),
+                            /*maxSize*/0, format, dataSpace, rotation,
+                            physicalCameraId, setId),
         mConsumer(nullptr),
         mTransform(0),
         mTraceFirstBuffer(true),
@@ -131,11 +135,13 @@
                                          int format,
                                          android_dataspace dataSpace,
                                          camera3_stream_rotation_t rotation,
+                                         const String8& physicalCameraId,
                                          uint64_t consumerUsage, nsecs_t timestampOffset,
                                          int setId) :
         Camera3IOStreamBase(id, type, width, height,
                             /*maxSize*/0,
-                            format, dataSpace, rotation, setId),
+                            format, dataSpace, rotation,
+                            physicalCameraId, setId),
         mTransform(0),
         mTraceFirstBuffer(true),
         mUseMonoTimestamp(false),
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 18b1901..824aef7 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -82,7 +82,8 @@
     Camera3OutputStream(int id, sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation,
-            nsecs_t timestampOffset, int setId = CAMERA3_STREAM_SET_ID_INVALID);
+            nsecs_t timestampOffset, const String8& physicalCameraId,
+            int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
     /**
      * Set up a stream for formats that have a variable buffer size for the same
@@ -93,7 +94,8 @@
     Camera3OutputStream(int id, sp<Surface> consumer,
             uint32_t width, uint32_t height, size_t maxSize, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation,
-            nsecs_t timestampOffset, int setId = CAMERA3_STREAM_SET_ID_INVALID);
+            nsecs_t timestampOffset, const String8& physicalCameraId,
+            int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
     /**
      * Set up a stream with deferred consumer for formats that have 2 dimensions, such as
@@ -103,6 +105,7 @@
     Camera3OutputStream(int id, uint32_t width, uint32_t height, int format,
             uint64_t consumerUsage, android_dataspace dataSpace,
             camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+            const String8& physicalCameraId,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
     virtual ~Camera3OutputStream();
@@ -194,6 +197,7 @@
     Camera3OutputStream(int id, camera3_stream_type_t type,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+            const String8& physicalCameraId,
             uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 1c9417b..2bb9ff7 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2016-2018 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.
@@ -27,10 +27,11 @@
         uint32_t width, uint32_t height, int format,
         uint64_t consumerUsage, android_dataspace dataSpace,
         camera3_stream_rotation_t rotation,
-        nsecs_t timestampOffset, int setId) :
+        nsecs_t timestampOffset, const String8& physicalCameraId,
+        int setId) :
         Camera3OutputStream(id, CAMERA3_STREAM_OUTPUT, width, height,
-                            format, dataSpace, rotation, consumerUsage,
-                            timestampOffset, setId) {
+                            format, dataSpace, rotation, physicalCameraId,
+                            consumerUsage, timestampOffset, setId) {
     size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
     if (surfaces.size() > consumerCount) {
         ALOGE("%s: Trying to add more consumers than the maximum ", __func__);
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index 6eab8bd..02b1c09 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2016-2018 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.
@@ -36,6 +36,7 @@
             uint32_t width, uint32_t height, int format,
             uint64_t consumerUsage, android_dataspace dataSpace,
             camera3_stream_rotation_t rotation, nsecs_t timestampOffset,
+            const String8& physicalCameraId,
             int setId = CAMERA3_STREAM_SET_ID_INVALID);
 
     virtual ~Camera3SharedOutputStream();
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index fbe8f4f..0d91620 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -47,7 +47,8 @@
 Camera3Stream::Camera3Stream(int id,
         camera3_stream_type type,
         uint32_t width, uint32_t height, size_t maxSize, int format,
-        android_dataspace dataSpace, camera3_stream_rotation_t rotation, int setId) :
+        android_dataspace dataSpace, camera3_stream_rotation_t rotation,
+        const String8& physicalCameraId, int setId) :
     camera3_stream(),
     mId(id),
     mSetId(setId),
@@ -64,7 +65,8 @@
     mLastMaxCount(Camera3StreamInterface::ALLOCATE_PIPELINE_MAX),
     mBufferLimitLatency(kBufferLimitLatencyBinSize),
     mFormatOverridden(false),
-    mOriginalFormat(-1) {
+    mOriginalFormat(-1),
+    mPhysicalCameraId(physicalCameraId) {
 
     camera3_stream::stream_type = type;
     camera3_stream::width = width;
@@ -74,6 +76,7 @@
     camera3_stream::rotation = rotation;
     camera3_stream::max_buffers = 0;
     camera3_stream::priv = NULL;
+    camera3_stream::physical_camera_id = mPhysicalCameraId.string();
 
     if ((format == HAL_PIXEL_FORMAT_BLOB || format == HAL_PIXEL_FORMAT_RAW_OPAQUE) &&
             maxSize == 0) {
@@ -140,6 +143,75 @@
     return mOriginalDataSpace;
 }
 
+status_t Camera3Stream::forceToIdle() {
+    ATRACE_CALL();
+    Mutex::Autolock l(mLock);
+    status_t res;
+
+    switch (mState) {
+        case STATE_ERROR:
+        case STATE_CONSTRUCTED:
+        case STATE_IN_CONFIG:
+        case STATE_PREPARING:
+        case STATE_IN_RECONFIG:
+            ALOGE("%s: Invalid state: %d", __FUNCTION__, mState);
+            res = NO_INIT;
+            break;
+        case STATE_CONFIGURED:
+            if (hasOutstandingBuffersLocked()) {
+                sp<StatusTracker> statusTracker = mStatusTracker.promote();
+                if (statusTracker != 0) {
+                    statusTracker->markComponentIdle(mStatusId, Fence::NO_FENCE);
+                }
+            }
+
+            mState = STATE_IN_IDLE;
+            res = OK;
+
+            break;
+        default:
+            ALOGE("%s: Unknown state %d", __FUNCTION__, mState);
+            res = NO_INIT;
+    }
+
+    return res;
+}
+
+status_t Camera3Stream::restoreConfiguredState() {
+    ATRACE_CALL();
+    Mutex::Autolock l(mLock);
+    status_t res;
+
+    switch (mState) {
+        case STATE_ERROR:
+        case STATE_CONSTRUCTED:
+        case STATE_IN_CONFIG:
+        case STATE_PREPARING:
+        case STATE_IN_RECONFIG:
+        case STATE_CONFIGURED:
+            ALOGE("%s: Invalid state: %d", __FUNCTION__, mState);
+            res = NO_INIT;
+            break;
+        case STATE_IN_IDLE:
+            if (hasOutstandingBuffersLocked()) {
+                sp<StatusTracker> statusTracker = mStatusTracker.promote();
+                if (statusTracker != 0) {
+                    statusTracker->markComponentActive(mStatusId);
+                }
+            }
+
+            mState = STATE_CONFIGURED;
+            res = OK;
+
+            break;
+        default:
+            ALOGE("%s: Unknown state %d", __FUNCTION__, mState);
+            res = NO_INIT;
+    }
+
+    return res;
+}
+
 camera3_stream* Camera3Stream::startConfiguration() {
     ATRACE_CALL();
     Mutex::Autolock l(mLock);
@@ -150,6 +222,7 @@
             ALOGE("%s: In error state", __FUNCTION__);
             return NULL;
         case STATE_CONSTRUCTED:
+        case STATE_IN_IDLE:
             // OK
             break;
         case STATE_IN_CONFIG:
@@ -179,6 +252,11 @@
         return NULL;
     }
 
+    if (mState == STATE_IN_IDLE) {
+        // Skip configuration.
+        return this;
+    }
+
     // Stop tracking if currently doing so
     if (mStatusId != StatusTracker::NO_STATUS_ID) {
         sp<StatusTracker> statusTracker = mStatusTracker.promote();
@@ -219,6 +297,9 @@
             ALOGE("%s: Cannot finish configuration that hasn't been started",
                     __FUNCTION__);
             return INVALID_OPERATION;
+        case STATE_IN_IDLE:
+            //Skip configuration in this state
+            return OK;
         default:
             ALOGE("%s: Unknown state", __FUNCTION__);
             return INVALID_OPERATION;
@@ -267,6 +348,7 @@
             return INVALID_OPERATION;
         case STATE_IN_CONFIG:
         case STATE_IN_RECONFIG:
+        case STATE_IN_IDLE:
             // OK
             break;
         case STATE_CONSTRUCTED:
@@ -282,7 +364,9 @@
     mUsage = mOldUsage;
     camera3_stream::max_buffers = mOldMaxBuffers;
 
-    mState = (mState == STATE_IN_RECONFIG) ? STATE_CONFIGURED : STATE_CONSTRUCTED;
+    mState = ((mState == STATE_IN_RECONFIG) || (mState == STATE_IN_IDLE)) ? STATE_CONFIGURED :
+            STATE_CONSTRUCTED;
+
     return OK;
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 6e7912e..f85dff2 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013-2018 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.
@@ -68,6 +68,12 @@
  *    duration.  In this state, only prepareNextBuffer() and cancelPrepare()
  *    may be called.
  *
+ *  STATE_IN_IDLE: This is a temporary state only intended to be used for input
+ *    streams and only for the case where we need to re-configure the camera device
+ *    while the input stream has an outstanding buffer. All other streams should not
+ *    be able to switch to this state. For them this is invalid and should be handled
+ *    as an unknown state.
+ *
  * Transition table:
  *
  *    <none>               => STATE_CONSTRUCTED:
@@ -98,6 +104,11 @@
  *        all stream buffers, or cancelPrepare is called.
  *    STATE_CONFIGURED     => STATE_ABANDONED:
  *        When the buffer queue of the stream is abandoned.
+ *    STATE_CONFIGURED     => STATE_IN_IDLE:
+ *        Only for an input stream which has an outstanding buffer.
+ *    STATE_IN_IDLE     => STATE_CONFIGURED:
+ *        After the internal re-configuration, the input should revert back to
+ *        the configured state.
  *
  * Status Tracking:
  *    Each stream is tracked by StatusTracker as a separate component,
@@ -108,7 +119,9 @@
  *
  *    - ACTIVE: One or more buffers have been handed out (with #getBuffer).
  *    - IDLE: All buffers have been returned (with #returnBuffer), and their
- *          respective release_fence(s) have been signaled.
+ *          respective release_fence(s) have been signaled. The only exception to this
+ *          rule is an input stream that moves to "STATE_IN_IDLE" during internal
+ *          re-configuration.
  *
  *    A typical use case is output streams. When the HAL has any buffers
  *    dequeued, the stream is marked ACTIVE. When the HAL returns all buffers
@@ -386,6 +399,19 @@
      */
     bool             isAbandoned() const;
 
+    /**
+     * Switch a configured stream with possibly outstanding buffers in idle
+     * state. Configuration for such streams will be skipped assuming there
+     * are no changes to the stream parameters.
+     */
+    status_t         forceToIdle();
+
+    /**
+     * Restore a forced idle stream to configured state, marking it active
+     * in case it contains outstanding buffers.
+     */
+    status_t         restoreConfiguredState();
+
   protected:
     const int mId;
     /**
@@ -414,7 +440,8 @@
         STATE_IN_RECONFIG,
         STATE_CONFIGURED,
         STATE_PREPARING,
-        STATE_ABANDONED
+        STATE_ABANDONED,
+        STATE_IN_IDLE
     } mState;
 
     mutable Mutex mLock;
@@ -422,7 +449,7 @@
     Camera3Stream(int id, camera3_stream_type type,
             uint32_t width, uint32_t height, size_t maxSize, int format,
             android_dataspace dataSpace, camera3_stream_rotation_t rotation,
-            int setId);
+            const String8& physicalCameraId, int setId);
 
     wp<Camera3StreamBufferFreedListener> mBufferFreedListener;
 
@@ -529,6 +556,7 @@
     bool mDataSpaceOverridden;
     android_dataspace mOriginalDataSpace;
 
+    String8 mPhysicalCameraId;
 }; // class Camera3Stream
 
 }; // namespace camera3
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 4980316..9f3746f 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -21,6 +21,16 @@
 
 # extractor libraries
 LOCAL_REQUIRED_MODULES := \
+    libaacextractor \
+    libamrextractor \
+    libflacextractor \
+    libmidiextractor \
+    libmkvextractor \
+    libmp3extractor \
+    libmp4extractor \
+    libmpeg2extractor \
+    liboggextractor \
+    libwavextractor \
     MediaComponents \
 
 LOCAL_SRC_FILES := main_extractorservice.cpp
diff --git a/services/soundtrigger/Android.mk b/services/soundtrigger/Android.mk
index ca44737..ad3666e 100644
--- a/services/soundtrigger/Android.mk
+++ b/services/soundtrigger/Android.mk
@@ -53,6 +53,7 @@
     libhidltransport \
     libbase \
     libaudiohal \
+    libaudiohal_deathhandler \
     android.hardware.soundtrigger@2.0 \
     android.hardware.soundtrigger@2.1 \
     android.hardware.audio.common@2.0 \