Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f42760c9 authored by Shuzhen Wang's avatar Shuzhen Wang Committed by Android (Google) Code Review
Browse files

Merge "camera: Support multiple physical camera requests"

parents 48758573 aebbe414
Loading
Loading
Loading
Loading
+42 −5
Original line number Diff line number Diff line
@@ -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 @@ status_t CaptureRequest::readFromParcel(const android::Parcel* parcel) {
        return BAD_VALUE;
    }

    mMetadata.clear();
    mSurfaceList.clear();
    mStreamIdxList.clear();
    mSurfaceIdxList.clear();
    mPhysicalCameraSettings.clear();

    status_t err = OK;

    if ((err = mMetadata.readFromParcel(parcel)) != OK) {
    int32_t settingsCount;
    if ((err = parcel->readInt32(&settingsCount)) != OK) {
        ALOGE("%s: Failed to read the settings count from parcel: %d", __FUNCTION__, err);
        return err;
    }

    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 CaptureRequest::writeToParcel(android::Parcel* parcel) const {

    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) {
+5 −1
Original line number Diff line number Diff line
@@ -40,7 +40,11 @@ struct CaptureRequest : public Parcelable {
    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;
+3 −2
Original line number Diff line number Diff line
@@ -372,7 +372,8 @@ CameraDevice::allocateCaptureRequest(
        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 @@ CameraDevice::allocateCaptureRequest(
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++) {
+71 −5
Original line number Diff line number Diff line
@@ -317,6 +317,9 @@ TEST(CameraServiceBinderTest, CheckBinderCameraService) {
    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 @@ protected:
        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 @@ TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) {
    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 @@ TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) {
        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 @@ TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) {
                /*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 @@ TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) {
        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, CheckBinderCameraDeviceUser) {
    }

};

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);
};
+1 −0
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@ TEST(VendorTagDescriptorTest, ConsistentAcrossParcel) {
    EXPECT_EQ(OK, vDescOriginal->writeToParcel(&p));
    p.setDataPosition(0);

    vDescParceled = new VendorTagDescriptor();
    ASSERT_EQ(OK, vDescParceled->readFromParcel(&p));

    // Ensure consistent tag count
Loading