Merge "AudioFlinger: allow shared record audio history for fast capture" into sc-dev
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 416884e..b4e4c5d 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -2587,7 +2587,9 @@
         case FOURCC("dvcC"):
         case FOURCC("dvvC"): {
 
-            CHECK_EQ(chunk_data_size, 24);
+            if (chunk_data_size != 24) {
+                return ERROR_MALFORMED;
+            }
 
             auto buffer = heapbuffer<uint8_t>(chunk_data_size);
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9eb7003..4fc60a4 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -828,12 +828,16 @@
             if (mask & AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER) s.append("top-front-center, ");
             if (mask & AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT) s.append("top-front-right, ");
             if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_LEFT) s.append("top-back-left, ");
-            if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_CENTER) s.append("top-back-center, " );
-            if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT) s.append("top-back-right, " );
-            if (mask & AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT) s.append("top-side-left, " );
-            if (mask & AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT) s.append("top-side-right, " );
-            if (mask & AUDIO_CHANNEL_OUT_HAPTIC_B) s.append("haptic-B, " );
-            if (mask & AUDIO_CHANNEL_OUT_HAPTIC_A) s.append("haptic-A, " );
+            if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_CENTER) s.append("top-back-center, ");
+            if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT) s.append("top-back-right, ");
+            if (mask & AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT) s.append("top-side-left, ");
+            if (mask & AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT) s.append("top-side-right, ");
+            if (mask & AUDIO_CHANNEL_OUT_BOTTOM_FRONT_LEFT) s.append("bottom-front-left, ");
+            if (mask & AUDIO_CHANNEL_OUT_BOTTOM_FRONT_CENTER) s.append("bottom-front-center, ");
+            if (mask & AUDIO_CHANNEL_OUT_BOTTOM_FRONT_RIGHT) s.append("bottom-front-right, ");
+            if (mask & AUDIO_CHANNEL_OUT_LOW_FREQUENCY_2) s.append("low_frequency_2, ");
+            if (mask & AUDIO_CHANNEL_OUT_HAPTIC_B) s.append("haptic-B, ");
+            if (mask & AUDIO_CHANNEL_OUT_HAPTIC_A) s.append("haptic-A, ");
             if (mask & ~AUDIO_CHANNEL_OUT_ALL) s.append("unknown,  ");
         } else {
             if (mask & AUDIO_CHANNEL_IN_LEFT) s.append("left, ");
@@ -852,8 +856,8 @@
             if (mask & AUDIO_CHANNEL_IN_BACK_RIGHT) s.append("back-right, ");
             if (mask & AUDIO_CHANNEL_IN_CENTER) s.append("center, ");
             if (mask & AUDIO_CHANNEL_IN_LOW_FREQUENCY) s.append("low freq, ");
-            if (mask & AUDIO_CHANNEL_IN_TOP_LEFT) s.append("top-left, " );
-            if (mask & AUDIO_CHANNEL_IN_TOP_RIGHT) s.append("top-right, " );
+            if (mask & AUDIO_CHANNEL_IN_TOP_LEFT) s.append("top-left, ");
+            if (mask & AUDIO_CHANNEL_IN_TOP_RIGHT) s.append("top-right, ");
             if (mask & AUDIO_CHANNEL_IN_VOICE_UPLINK) s.append("voice-uplink, ");
             if (mask & AUDIO_CHANNEL_IN_VOICE_DNLINK) s.append("voice-dnlink, ");
             if (mask & ~AUDIO_CHANNEL_IN_ALL) s.append("unknown,  ");
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 07c889b..c28c24b 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -82,6 +82,7 @@
         "device3/RotateAndCropMapper.cpp",
         "device3/Camera3OutputStreamInterface.cpp",
         "device3/Camera3OutputUtils.cpp",
+        "device3/Camera3DeviceInjectionMethods.cpp",
         "gui/RingBufferConsumer.cpp",
         "hidl/AidlCameraDeviceCallbacks.cpp",
         "hidl/AidlCameraServiceListener.cpp",
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index d93b9e5..d05a2e1 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -49,6 +49,7 @@
 #include <utils/Timers.h>
 #include <cutils/properties.h>
 
+#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
 
 #include "utils/CameraTraces.h"
@@ -358,6 +359,8 @@
         }
     }
 
+    mInjectionMethods = new Camera3DeviceInjectionMethods(this);
+
     return OK;
 }
 
@@ -431,6 +434,10 @@
             mStatusTracker->join();
         }
 
+        if (mInjectionMethods->isInjecting()) {
+            mInjectionMethods->stopInjection();
+        }
+
         HalInterface* interface;
         {
             Mutex::Autolock l(mLock);
@@ -1829,7 +1836,6 @@
     return res;
 }
 
-
 void Camera3Device::internalUpdateStatusLocked(Status status) {
     mStatus = status;
     mRecentStatusUpdates.add(mStatus);
@@ -2820,6 +2826,19 @@
         mRequestBufferSM.onStreamsConfigured();
     }
 
+    // Since the streams configuration of the injection camera is based on the internal camera, we
+    // must wait until the internal camera configure streams before calling injectCamera() to
+    // configure the injection streams.
+    if (mInjectionMethods->isInjecting()) {
+        ALOGV("%s: Injection camera %s: Start to configure streams.",
+              __FUNCTION__, mInjectionMethods->getInjectedCamId().string());
+        res = mInjectionMethods->injectCamera(config, bufferSizes);
+        if (res != OK) {
+            ALOGE("Can't finish inject camera process!");
+            return res;
+        }
+    }
+
     return OK;
 }
 
@@ -3524,6 +3543,146 @@
     return res;
 }
 
+status_t Camera3Device::HalInterface::configureInjectedStreams(
+        const camera_metadata_t* sessionParams, camera_stream_configuration* config,
+        const std::vector<uint32_t>& bufferSizes,
+        const CameraMetadata& cameraCharacteristics) {
+    ATRACE_NAME("InjectionCameraHal::configureStreams");
+    if (!valid()) return INVALID_OPERATION;
+    status_t res = OK;
+
+    if (config->input_is_multi_resolution) {
+        ALOGE("%s: Injection camera device doesn't support multi-resolution input "
+                "stream", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    // Convert stream config to HIDL
+    std::set<int> activeStreams;
+    device::V3_2::StreamConfiguration requestedConfiguration3_2;
+    device::V3_4::StreamConfiguration requestedConfiguration3_4;
+    device::V3_7::StreamConfiguration requestedConfiguration3_7;
+    requestedConfiguration3_2.streams.resize(config->num_streams);
+    requestedConfiguration3_4.streams.resize(config->num_streams);
+    requestedConfiguration3_7.streams.resize(config->num_streams);
+    for (size_t i = 0; i < config->num_streams; i++) {
+        device::V3_2::Stream& dst3_2 = requestedConfiguration3_2.streams[i];
+        device::V3_4::Stream& dst3_4 = requestedConfiguration3_4.streams[i];
+        device::V3_7::Stream& dst3_7 = requestedConfiguration3_7.streams[i];
+        camera3::camera_stream_t* src = config->streams[i];
+
+        Camera3Stream* cam3stream = Camera3Stream::cast(src);
+        cam3stream->setBufferFreedListener(this);
+        int streamId = cam3stream->getId();
+        StreamType streamType;
+        switch (src->stream_type) {
+            case CAMERA_STREAM_OUTPUT:
+                streamType = StreamType::OUTPUT;
+                break;
+            case CAMERA_STREAM_INPUT:
+                streamType = StreamType::INPUT;
+                break;
+            default:
+                ALOGE("%s: Stream %d: Unsupported stream type %d", __FUNCTION__,
+                        streamId, config->streams[i]->stream_type);
+            return BAD_VALUE;
+        }
+        dst3_2.id = streamId;
+        dst3_2.streamType = streamType;
+        dst3_2.width = src->width;
+        dst3_2.height = src->height;
+        dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
+        dst3_2.rotation =
+                mapToStreamRotation((camera_stream_rotation_t)src->rotation);
+        // For HidlSession version 3.5 or newer, the format and dataSpace sent
+        // to HAL are original, not the overridden ones.
+        if (mHidlSession_3_5 != nullptr) {
+            dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden()
+                                            ? cam3stream->getOriginalFormat()
+                                            : src->format);
+            dst3_2.dataSpace =
+                    mapToHidlDataspace(cam3stream->isDataSpaceOverridden()
+                                    ? cam3stream->getOriginalDataSpace()
+                                    : src->data_space);
+        } else {
+            dst3_2.format = mapToPixelFormat(src->format);
+            dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
+        }
+        dst3_4.v3_2 = dst3_2;
+        dst3_4.bufferSize = bufferSizes[i];
+        if (src->physical_camera_id != nullptr) {
+            dst3_4.physicalCameraId = src->physical_camera_id;
+        }
+        dst3_7.v3_4 = dst3_4;
+        dst3_7.groupId = cam3stream->getHalStreamGroupId();
+        dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
+        size_t j = 0;
+        for (int mode : src->sensor_pixel_modes_used) {
+            dst3_7.sensorPixelModesUsed[j++] =
+                    static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
+        }
+        activeStreams.insert(streamId);
+        // Create Buffer ID map if necessary
+        mBufferRecords.tryCreateBufferCache(streamId);
+    }
+    // remove BufferIdMap for deleted streams
+    mBufferRecords.removeInactiveBufferCaches(activeStreams);
+
+    StreamConfigurationMode operationMode;
+    res = mapToStreamConfigurationMode(
+            (camera_stream_configuration_mode_t)config->operation_mode,
+            /*out*/ &operationMode);
+    if (res != OK) {
+        return res;
+    }
+    requestedConfiguration3_7.operationMode = operationMode;
+    size_t sessionParamSize = get_camera_metadata_size(sessionParams);
+    requestedConfiguration3_7.operationMode = operationMode;
+    requestedConfiguration3_7.sessionParams.setToExternal(
+            reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+            sessionParamSize);
+
+    // See which version of HAL we have
+    if (mHidlSession_3_7 != nullptr) {
+        requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
+        requestedConfiguration3_7.multiResolutionInputImage =
+                config->input_is_multi_resolution;
+
+        const camera_metadata_t* rawMetadata = cameraCharacteristics.getAndLock();
+        ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {};
+        hidlChars.setToExternal(
+                reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(rawMetadata)),
+                get_camera_metadata_size(rawMetadata));
+        cameraCharacteristics.unlock(rawMetadata);
+
+        sp<hardware::camera::device::V3_7::ICameraInjectionSession>
+                hidlInjectionSession_3_7;
+        auto castInjectionResult_3_7 =
+                device::V3_7::ICameraInjectionSession::castFrom(mHidlSession_3_7);
+        if (castInjectionResult_3_7.isOk()) {
+            hidlInjectionSession_3_7 = castInjectionResult_3_7;
+        } else {
+            ALOGE("%s: Transaction error: %s", __FUNCTION__,
+                    castInjectionResult_3_7.description().c_str());
+            return DEAD_OBJECT;
+        }
+
+        auto err = hidlInjectionSession_3_7->configureInjectionStreams(
+                requestedConfiguration3_7, hidlChars);
+        if (!err.isOk()) {
+            ALOGE("%s: Transaction error: %s", __FUNCTION__,
+                    err.description().c_str());
+            return DEAD_OBJECT;
+        }
+    } else {
+        ALOGE("%s: mHidlSession_3_7 does not exist, the lowest version of injection "
+                "session is 3.7", __FUNCTION__);
+        return DEAD_OBJECT;
+    }
+
+    return res;
+}
+
 status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera_capture_request_t* request,
         /*out*/device::V3_2::CaptureRequest* captureRequest,
         /*out*/std::vector<native_handle_t*>* handlesCreated,
@@ -5724,6 +5883,18 @@
     return changed;
 }
 
+status_t Camera3Device::RequestThread::setHalInterface(
+        sp<HalInterface> newHalInterface) {
+    if (newHalInterface.get() == nullptr) {
+        ALOGE("%s: The newHalInterface does not exist!", __FUNCTION__);
+        return DEAD_OBJECT;
+    }
+
+    mInterface = newHalInterface;
+
+    return OK;
+}
+
 /**
  * PreparerThread inner class methods
  */
@@ -6367,4 +6538,58 @@
     return mRequestThread->setCameraMute(enabled);
 }
 
+status_t Camera3Device::injectCamera(const String8& injectedCamId,
+                                     sp<CameraProviderManager> manager) {
+    ALOGI("%s Injection camera: injectedCamId = %s", __FUNCTION__, injectedCamId.string());
+    ATRACE_CALL();
+    Mutex::Autolock il(mInterfaceLock);
+
+    status_t res = NO_ERROR;
+    if (mInjectionMethods->isInjecting()) {
+        if (injectedCamId == mInjectionMethods->getInjectedCamId()) {
+            return OK;
+        } else {
+            res = mInjectionMethods->stopInjection();
+            if (res != OK) {
+                ALOGE("%s: Failed to stop the injection camera! ret != NO_ERROR: %d",
+                        __FUNCTION__, res);
+                return res;
+            }
+        }
+    }
+
+    res = mInjectionMethods->injectionInitialize(injectedCamId, manager, this);
+    if (res != OK) {
+        ALOGE("%s: Failed to initialize the injection camera! ret != NO_ERROR: %d",
+                __FUNCTION__, res);
+        return res;
+    }
+
+    camera3::camera_stream_configuration injectionConfig;
+    std::vector<uint32_t> injectionBufferSizes;
+    mInjectionMethods->getInjectionConfig(&injectionConfig, &injectionBufferSizes);
+    // When the second display of android is cast to the remote device, and the opened camera is
+    // also cast to the second display, in this case, because the camera has configured the streams
+    // at this time, we can directly call injectCamera() to replace the internal camera with
+    // injection camera.
+    if (mOperatingMode >= 0 && injectionConfig.num_streams > 0
+                && injectionBufferSizes.size() > 0) {
+        ALOGV("%s: The opened camera is directly cast to the remote device.", __FUNCTION__);
+        res = mInjectionMethods->injectCamera(
+                injectionConfig, injectionBufferSizes);
+        if (res != OK) {
+            ALOGE("Can't finish inject camera process!");
+            return res;
+        }
+    }
+
+    return OK;
+}
+
+status_t Camera3Device::stopInjection() {
+    ALOGI("%s: Injection camera: stopInjection", __FUNCTION__);
+    Mutex::Autolock il(mInterfaceLock);
+    return mInjectionMethods->stopInjection();
+}
+
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d9e89fd..f962c78 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -263,6 +263,18 @@
     wp<camera3::StatusTracker> getStatusTracker() { return mStatusTracker; }
 
     /**
+     * The injection camera session to replace the internal camera
+     * session.
+     */
+    status_t injectCamera(const String8& injectedCamId,
+                          sp<CameraProviderManager> manager);
+
+    /**
+     * Stop the injection camera and restore to internal camera session.
+     */
+    status_t stopInjection();
+
+    /**
      * Helper functions to map between framework and HIDL values
      */
     static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
@@ -363,6 +375,13 @@
                 /*inout*/ camera_stream_configuration_t *config,
                 const std::vector<uint32_t>& bufferSizes);
 
+        // The injection camera configures the streams to hal.
+        status_t configureInjectedStreams(
+                const camera_metadata_t* sessionParams,
+                /*inout*/ camera_stream_configuration_t* config,
+                const std::vector<uint32_t>& bufferSizes,
+                const CameraMetadata& cameraCharacteristics);
+
         // When the call succeeds, the ownership of acquire fences in requests is transferred to
         // HalInterface. More specifically, the current implementation will send the fence to
         // HAL process and close the FD in cameraserver process. When the call fails, the ownership
@@ -900,6 +919,9 @@
                 camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue);
 
         status_t setCameraMute(bool enabled);
+
+        status_t setHalInterface(sp<HalInterface> newHalInterface);
+
       protected:
 
         virtual bool threadLoop();
@@ -1321,6 +1343,75 @@
     // Whether the HAL supports camera muting via test pattern
     bool mSupportCameraMute = false;
 
+    // Injection camera related methods.
+    class Camera3DeviceInjectionMethods : public virtual RefBase {
+      public:
+        Camera3DeviceInjectionMethods(wp<Camera3Device> parent);
+
+        ~Camera3DeviceInjectionMethods();
+
+        // Initialize the injection camera and generate an hal interface.
+        status_t injectionInitialize(
+                const String8& injectedCamId, sp<CameraProviderManager> manager,
+                const sp<
+                    android::hardware::camera::device::V3_2 ::ICameraDeviceCallback>&
+                    callback);
+
+        // Injection camera will replace the internal camera and configure streams
+        // when device is IDLE and request thread is paused.
+        status_t injectCamera(
+                camera3::camera_stream_configuration& injectionConfig,
+                std::vector<uint32_t>& injectionBufferSizes);
+
+        // Stop the injection camera and switch back to backup hal interface.
+        status_t stopInjection();
+
+        bool isInjecting();
+
+        const String8& getInjectedCamId() const;
+
+        void getInjectionConfig(/*out*/ camera3::camera_stream_configuration* injectionConfig,
+                /*out*/ std::vector<uint32_t>* injectionBufferSizes);
+
+      private:
+        // Configure the streams of injection camera, it need wait until the
+        // output streams are created and configured to the original camera before
+        // proceeding.
+        status_t injectionConfigureStreams(
+                camera3::camera_stream_configuration& injectionConfig,
+                std::vector<uint32_t>& injectionBufferSizes);
+
+        // Disconnect the injection camera and delete the hal interface.
+        void injectionDisconnectImpl();
+
+        // Use injection camera hal interface to replace and backup original
+        // camera hal interface.
+        status_t replaceHalInterface(sp<HalInterface> newHalInterface,
+                bool keepBackup);
+
+        wp<Camera3Device> mParent;
+
+        // Backup of the original camera hal interface.
+        sp<HalInterface> mBackupHalInterface;
+
+        // Generated injection camera hal interface.
+        sp<HalInterface> mInjectedCamHalInterface;
+
+        // Copy the configuration of the internal camera.
+        camera3::camera_stream_configuration mInjectionConfig;
+
+        // Copy the bufferSizes of the output streams of the internal camera.
+        std::vector<uint32_t> mInjectionBufferSizes;
+
+        // Synchronizes access to injection camera between initialize and
+        // disconnect.
+        Mutex mInjectionLock;
+
+        // The injection camera ID.
+        String8 mInjectedCamId;
+    };
+    sp<Camera3DeviceInjectionMethods> mInjectionMethods;
+
 }; // class Camera3Device
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
new file mode 100644
index 0000000..f145dac
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2021 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 "Camera3DeviceInjectionMethods"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "common/CameraProviderManager.h"
+#include "device3/Camera3Device.h"
+
+namespace android {
+
+using hardware::camera::device::V3_2::ICameraDeviceSession;
+
+Camera3Device::Camera3DeviceInjectionMethods::Camera3DeviceInjectionMethods(
+        wp<Camera3Device> parent)
+        : mParent(parent) {
+    ALOGV("%s: Created injection camera methods", __FUNCTION__);
+}
+
+Camera3Device::Camera3DeviceInjectionMethods::~Camera3DeviceInjectionMethods() {
+    ALOGV("%s: Removed injection camera methods", __FUNCTION__);
+    injectionDisconnectImpl();
+}
+
+status_t Camera3Device::Camera3DeviceInjectionMethods::injectionInitialize(
+        const String8& injectedCamId, sp<CameraProviderManager> manager,
+        const sp<android::hardware::camera::device::V3_2::ICameraDeviceCallback>&
+                callback) {
+    ATRACE_CALL();
+    Mutex::Autolock lock(mInjectionLock);
+
+    if (manager == nullptr) {
+        ALOGE("%s: manager does not exist!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    sp<Camera3Device> parent = mParent.promote();
+    if (parent == nullptr) {
+        ALOGE("%s: parent does not exist!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    mInjectedCamId = injectedCamId;
+    sp<ICameraDeviceSession> session;
+    ATRACE_BEGIN("Injection CameraHal::openSession");
+    status_t res = manager->openSession(injectedCamId.string(), callback,
+                                          /*out*/ &session);
+    ATRACE_END();
+    if (res != OK) {
+        ALOGE("Injection camera could not open camera session: %s (%d)",
+                strerror(-res), res);
+        return res;
+    }
+
+    std::shared_ptr<RequestMetadataQueue> queue;
+    auto requestQueueRet =
+        session->getCaptureRequestMetadataQueue([&queue](const auto& descriptor) {
+            queue = std::make_shared<RequestMetadataQueue>(descriptor);
+            if (!queue->isValid() || queue->availableToWrite() <= 0) {
+                ALOGE("Injection camera HAL returns empty request metadata fmq, not "
+                        "use it");
+                queue = nullptr;
+                // don't use the queue onwards.
+            }
+        });
+    if (!requestQueueRet.isOk()) {
+        ALOGE("Injection camera transaction error when getting request metadata fmq: "
+                "%s, not use it", requestQueueRet.description().c_str());
+        return DEAD_OBJECT;
+    }
+
+    std::unique_ptr<ResultMetadataQueue>& resQueue = parent->mResultMetadataQueue;
+    auto resultQueueRet = session->getCaptureResultMetadataQueue(
+        [&resQueue](const auto& descriptor) {
+            resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
+            if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+                ALOGE("Injection camera HAL returns empty result metadata fmq, not use "
+                        "it");
+                resQueue = nullptr;
+                // Don't use the resQueue onwards.
+            }
+        });
+    if (!resultQueueRet.isOk()) {
+        ALOGE("Injection camera transaction error when getting result metadata queue "
+                "from camera session: %s", resultQueueRet.description().c_str());
+        return DEAD_OBJECT;
+    }
+    IF_ALOGV() {
+        session->interfaceChain(
+                [](::android::hardware::hidl_vec<::android::hardware::hidl_string>
+                        interfaceChain) {
+                        ALOGV("Injection camera session interface chain:");
+                        for (const auto& iface : interfaceChain) {
+                            ALOGV("  %s", iface.c_str());
+                        }
+                });
+    }
+
+    ALOGV("%s: Injection camera interface = new HalInterface()", __FUNCTION__);
+    mInjectedCamHalInterface =
+            new HalInterface(session, queue, parent->mUseHalBufManager,
+                       parent->mSupportOfflineProcessing);
+    if (mInjectedCamHalInterface == nullptr) {
+        ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
+        return DEAD_OBJECT;
+    }
+
+    return OK;
+}
+
+status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(
+        camera3::camera_stream_configuration& injectionConfig,
+        std::vector<uint32_t>& injectionBufferSizes) {
+    status_t res = NO_ERROR;
+    mInjectionConfig = injectionConfig;
+    mInjectionBufferSizes = injectionBufferSizes;
+
+    if (mInjectedCamHalInterface == nullptr) {
+        ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
+        return DEAD_OBJECT;
+    }
+
+    sp<Camera3Device> parent = mParent.promote();
+    if (parent == nullptr) {
+        ALOGE("%s: parent does not exist!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    nsecs_t maxExpectedDuration = parent->getExpectedInFlightDuration();
+    bool wasActive = false;
+    if (parent->mStatus == STATUS_ACTIVE) {
+        ALOGV("%s: Let the device be IDLE and the request thread is paused",
+                __FUNCTION__);
+        parent->mPauseStateNotify = true;
+        res = parent->internalPauseAndWaitLocked(maxExpectedDuration);
+        if (res != OK) {
+            ALOGE("%s: Can't pause captures to inject camera!", __FUNCTION__);
+            return res;
+        }
+        wasActive = true;
+    }
+
+    ALOGV("%s: Injection camera: replaceHalInterface", __FUNCTION__);
+    res = replaceHalInterface(mInjectedCamHalInterface, true);
+    if (res != OK) {
+        ALOGE("%s: Failed to replace the new HalInterface!", __FUNCTION__);
+        injectionDisconnectImpl();
+        return res;
+    }
+
+    res = parent->mRequestThread->setHalInterface(mInjectedCamHalInterface);
+    if (res != OK) {
+        ALOGE("%s: Failed to set new HalInterface in RequestThread!", __FUNCTION__);
+        replaceHalInterface(mBackupHalInterface, false);
+        injectionDisconnectImpl();
+        return res;
+    }
+
+    parent->mNeedConfig = true;
+    res = injectionConfigureStreams(injectionConfig, injectionBufferSizes);
+    parent->mNeedConfig = false;
+    if (res != OK) {
+        ALOGE("Can't injectionConfigureStreams device for streams:  %d: %s "
+                "(%d)", parent->mNextStreamId, strerror(-res), res);
+        replaceHalInterface(mBackupHalInterface, false);
+        injectionDisconnectImpl();
+        return res;
+    }
+
+    if (wasActive) {
+        ALOGV("%s: Restarting activity to inject camera", __FUNCTION__);
+        // Reuse current operating mode and session parameters for new stream
+        // config.
+        parent->internalUpdateStatusLocked(STATUS_ACTIVE);
+    }
+
+    return OK;
+}
+
+status_t Camera3Device::Camera3DeviceInjectionMethods::stopInjection() {
+    status_t res = NO_ERROR;
+
+    sp<Camera3Device> parent = mParent.promote();
+    if (parent == nullptr) {
+        ALOGE("%s: parent does not exist!", __FUNCTION__);
+        return DEAD_OBJECT;
+    }
+
+    nsecs_t maxExpectedDuration = parent->getExpectedInFlightDuration();
+    bool wasActive = false;
+    if (parent->mStatus == STATUS_ACTIVE) {
+        ALOGV("%s: Let the device be IDLE and the request thread is paused",
+                __FUNCTION__);
+        parent->mPauseStateNotify = true;
+        res = parent->internalPauseAndWaitLocked(maxExpectedDuration);
+        if (res != OK) {
+            ALOGE("%s: Can't pause captures to stop injection!", __FUNCTION__);
+            return res;
+        }
+        wasActive = true;
+    }
+
+    res = replaceHalInterface(mBackupHalInterface, false);
+    if (res != OK) {
+        ALOGE("%s: Failed to restore the backup HalInterface!", __FUNCTION__);
+        injectionDisconnectImpl();
+        return res;
+    }
+    injectionDisconnectImpl();
+
+    if (wasActive) {
+        ALOGV("%s: Restarting activity to stop injection", __FUNCTION__);
+        // Reuse current operating mode and session parameters for new stream
+        // config.
+        parent->internalUpdateStatusLocked(STATUS_ACTIVE);
+    }
+
+    return OK;
+}
+
+bool Camera3Device::Camera3DeviceInjectionMethods::isInjecting() {
+    if (mInjectedCamHalInterface == nullptr) {
+        return false;
+    } else {
+        return true;
+    }
+}
+
+const String8& Camera3Device::Camera3DeviceInjectionMethods::getInjectedCamId()
+        const {
+    return mInjectedCamId;
+}
+
+void Camera3Device::Camera3DeviceInjectionMethods::getInjectionConfig(
+        /*out*/ camera3::camera_stream_configuration* injectionConfig,
+        /*out*/ std::vector<uint32_t>* injectionBufferSizes) {
+    if (injectionConfig == nullptr || injectionBufferSizes == nullptr) {
+        ALOGE("%s: Injection configuration arguments must not be null!", __FUNCTION__);
+        return;
+    }
+
+    *injectionConfig = mInjectionConfig;
+    *injectionBufferSizes = mInjectionBufferSizes;
+}
+
+
+status_t Camera3Device::Camera3DeviceInjectionMethods::injectionConfigureStreams(
+        camera3::camera_stream_configuration& injectionConfig,
+        std::vector<uint32_t>& injectionBufferSizes) {
+    ATRACE_CALL();
+    status_t res = NO_ERROR;
+
+    sp<Camera3Device> parent = mParent.promote();
+    if (parent == nullptr) {
+        ALOGE("%s: parent does not exist!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    if (parent->mOperatingMode < 0) {
+        ALOGE("Invalid operating mode: %d", parent->mOperatingMode);
+        return BAD_VALUE;
+    }
+
+    // Start configuring the streams
+    ALOGV("%s: Injection camera %s: Starting stream configuration", __FUNCTION__,
+            mInjectedCamId.string());
+
+    parent->mPreparerThread->pause();
+
+    // Do the HAL configuration; will potentially touch stream
+    // max_buffers, usage, and priv fields, as well as data_space and format
+    // fields for IMPLEMENTATION_DEFINED formats.
+
+    const camera_metadata_t* sessionBuffer = parent->mSessionParams.getAndLock();
+    res = mInjectedCamHalInterface->configureInjectedStreams(
+            sessionBuffer, &injectionConfig, injectionBufferSizes,
+            parent->mDeviceInfo);
+    parent->mSessionParams.unlock(sessionBuffer);
+
+    if (res == BAD_VALUE) {
+        // HAL rejected this set of streams as unsupported, clean up config
+        // attempt and return to unconfigured state
+        ALOGE("Set of requested outputs not supported by HAL");
+        parent->cancelStreamsConfigurationLocked();
+        return BAD_VALUE;
+    } else if (res != OK) {
+        // Some other kind of error from configure_streams - this is not
+        // expected
+        ALOGE("Unable to configure streams with HAL: %s (%d)", strerror(-res),
+                  res);
+        return res;
+    }
+
+    for (size_t i = 0; i < parent->mOutputStreams.size(); i++) {
+        sp<camera3::Camera3OutputStreamInterface> outputStream =
+                parent->mOutputStreams[i];
+        mInjectedCamHalInterface->onStreamReConfigured(outputStream->getId());
+    }
+
+    // Request thread needs to know to avoid using repeat-last-settings protocol
+    // across configure_streams() calls
+    parent->mRequestThread->configurationComplete(
+            parent->mIsConstrainedHighSpeedConfiguration, parent->mSessionParams,
+            parent->mGroupIdPhysicalCameraMap);
+
+    parent->internalUpdateStatusLocked(STATUS_CONFIGURED);
+
+    ALOGV("%s: Injection camera %s: Stream configuration complete", __FUNCTION__,
+            mInjectedCamId.string());
+
+    auto rc = parent->mPreparerThread->resume();
+
+    if (rc != OK) {
+        ALOGE("%s: Injection camera %s: Preparer thread failed to resume!",
+                 __FUNCTION__, mInjectedCamId.string());
+        return rc;
+    }
+
+    return OK;
+}
+
+void Camera3Device::Camera3DeviceInjectionMethods::injectionDisconnectImpl() {
+    ATRACE_CALL();
+    ALOGI("%s: Injection camera disconnect", __FUNCTION__);
+
+    mBackupHalInterface = nullptr;
+    HalInterface* interface = nullptr;
+    {
+        Mutex::Autolock lock(mInjectionLock);
+        if (mInjectedCamHalInterface != nullptr) {
+            interface = mInjectedCamHalInterface.get();
+            // Call close without internal mutex held, as the HAL close may need
+            // to wait on assorted callbacks,etc, to complete before it can
+            // return.
+        }
+    }
+
+    if (interface != nullptr) {
+        interface->close();
+    }
+
+    {
+        Mutex::Autolock lock(mInjectionLock);
+        if (mInjectedCamHalInterface != nullptr) {
+            mInjectedCamHalInterface->clear();
+            mInjectedCamHalInterface = nullptr;
+        }
+    }
+}
+
+status_t Camera3Device::Camera3DeviceInjectionMethods::replaceHalInterface(
+        sp<HalInterface> newHalInterface, bool keepBackup) {
+    Mutex::Autolock lock(mInjectionLock);
+    if (newHalInterface.get() == nullptr) {
+        ALOGE("%s: The newHalInterface does not exist, to stop replacing.",
+                __FUNCTION__);
+        return DEAD_OBJECT;
+    }
+
+    sp<Camera3Device> parent = mParent.promote();
+    if (parent == nullptr) {
+        ALOGE("%s: parent does not exist!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    if (keepBackup && mBackupHalInterface == nullptr) {
+        mBackupHalInterface = parent->mInterface;
+    } else if (!keepBackup) {
+        mBackupHalInterface = nullptr;
+    }
+    parent->mInterface = newHalInterface;
+
+    return OK;
+}
+
+};  // namespace android
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
index 281a4ce..2378f33 100644
--- a/services/mediametrics/statsd_extractor.cpp
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -52,9 +52,6 @@
     //
     ::android::stats::mediametrics::ExtractorData metrics_proto;
 
-    // flesh out the protobuf we'll hand off with our data
-    //
-
     std::string format;
     if (item->getString("android.media.mediaextractor.fmt", &format)) {
         metrics_proto.set_format(format);
@@ -86,7 +83,6 @@
       metrics_proto.set_entry_point(entry_point);
     }
 
-    // android.media.mediaextractor.logSessionId        string
     std::string log_session_id;
     if (item->getString("android.media.mediaextractor.logSessionId", &log_session_id)) {
         metrics_proto.set_log_session_id(log_session_id);
diff --git a/services/mediametrics/statsd_mediaparser.cpp b/services/mediametrics/statsd_mediaparser.cpp
index 6cceb06..af2946b 100644
--- a/services/mediametrics/statsd_mediaparser.cpp
+++ b/services/mediametrics/statsd_mediaparser.cpp
@@ -39,7 +39,6 @@
 bool statsd_mediaparser(const std::shared_ptr<const mediametrics::Item>& item,
         const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
 {
-    static constexpr bool enabled_statsd = true; // TODO: Remove, dup with dump2StatsdInternal().
     if (item == nullptr) return false;
 
     const nsecs_t timestamp_nanos = MediaMetricsService::roundTime(item->getTimestamp());
@@ -82,28 +81,25 @@
     std::string logSessionId;
     item->getString("android.media.mediaparser.logSessionId", &logSessionId);
 
-    if (enabled_statsd) {
-        (void) android::util::stats_write(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED,
-                                   timestamp_nanos,
-                                   package_name.c_str(),
-                                   package_version_code,
-                                   parserName.c_str(),
-                                   createdByName,
-                                   parserPool.c_str(),
-                                   lastException.c_str(),
-                                   resourceByteCount,
-                                   durationMillis,
-                                   trackMimeTypes.c_str(),
-                                   trackCodecs.c_str(),
-                                   alteredParameters.c_str(),
-                                   videoWidth,
-                                   videoHeight,
-                                   logSessionId.c_str());
-    } else {
-        ALOGV("NOT sending MediaParser media metrics.");
-    }
+    int result = android::util::stats_write(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED,
+                               timestamp_nanos,
+                               package_name.c_str(),
+                               package_version_code,
+                               parserName.c_str(),
+                               createdByName,
+                               parserPool.c_str(),
+                               lastException.c_str(),
+                               resourceByteCount,
+                               durationMillis,
+                               trackMimeTypes.c_str(),
+                               trackCodecs.c_str(),
+                               alteredParameters.c_str(),
+                               videoWidth,
+                               videoHeight,
+                               logSessionId.c_str());
+
     std::stringstream log;
-    log << "result:" << "(result)" << " {"
+    log << "result:" << result << " {"
             << " mediametrics_mediaparser_reported:"
             << android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED
             << " timestamp_nanos:" << timestamp_nanos