diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp index 98608da774..09b85d5490 100644 --- a/camera/ndk/NdkCameraDevice.cpp +++ b/camera/ndk/NdkCameraDevice.cpp @@ -78,7 +78,34 @@ camera_status_t ACameraDevice_createCaptureRequest( ALOGE("%s: unknown template ID %d", __FUNCTION__, templateId); return ACAMERA_ERROR_INVALID_PARAMETER; } - return device->createCaptureRequest(templateId, request); + return device->createCaptureRequest(templateId, nullptr /*physicalIdList*/, request); +} + +EXPORT +camera_status_t ACameraDevice_createCaptureRequest_withPhysicalIds( + const ACameraDevice* device, + ACameraDevice_request_template templateId, + const ACameraIdList* physicalCameraIdList, + ACaptureRequest** request) { + ATRACE_CALL(); + if (device == nullptr || request == nullptr || physicalCameraIdList == nullptr) { + ALOGE("%s: invalid argument! device %p request %p, physicalCameraIdList %p", + __FUNCTION__, device, request, physicalCameraIdList); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + switch (templateId) { + case TEMPLATE_PREVIEW: + case TEMPLATE_STILL_CAPTURE: + case TEMPLATE_RECORD: + case TEMPLATE_VIDEO_SNAPSHOT: + case TEMPLATE_ZERO_SHUTTER_LAG: + case TEMPLATE_MANUAL: + break; + default: + ALOGE("%s: unknown template ID %d", __FUNCTION__, templateId); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + return device->createCaptureRequest(templateId, physicalCameraIdList, request); } EXPORT diff --git a/camera/ndk/NdkCaptureRequest.cpp b/camera/ndk/NdkCaptureRequest.cpp index c64de3ee4d..87de4a9ba3 100644 --- a/camera/ndk/NdkCaptureRequest.cpp +++ b/camera/ndk/NdkCaptureRequest.cpp @@ -97,6 +97,27 @@ camera_status_t ACaptureRequest_getConstEntry( return req->settings->getConstEntry(tag, entry); } +EXPORT +camera_status_t ACaptureRequest_getConstEntry_physicalCamera( + const ACaptureRequest* req, const char* physicalId, + uint32_t tag, ACameraMetadata_const_entry* entry) { + ATRACE_CALL(); + if (req == nullptr || entry == nullptr || physicalId == nullptr) { + ALOGE("%s: invalid argument! req %p, tag 0x%x, entry %p, physicalId %p", + __FUNCTION__, req, tag, entry, physicalId); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + + const auto& physicalSettings = req->physicalSettings.find(physicalId); + if (physicalSettings == req->physicalSettings.end()) { + ALOGE("%s: Failed to find metadata for physical camera id %s", + __FUNCTION__, physicalId); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + + return physicalSettings->second->getConstEntry(tag, entry); +} + EXPORT camera_status_t ACaptureRequest_getAllTags( const ACaptureRequest* req, /*out*/int32_t* numTags, /*out*/const uint32_t** tags) { @@ -131,6 +152,34 @@ SET_ENTRY(rational,ACameraMetadata_rational) #undef SET_ENTRY +#define SET_PHYSICAL_ENTRY(NAME,NDK_TYPE) \ +EXPORT \ +camera_status_t ACaptureRequest_setEntry_physicalCamera_##NAME( \ + ACaptureRequest* req, const char* physicalId, uint32_t tag, \ + uint32_t count, const NDK_TYPE* data) { \ + ATRACE_CALL(); \ + if (req == nullptr || (count > 0 && data == nullptr) || physicalId == nullptr) { \ + ALOGE("%s: invalid argument! req %p, tag 0x%x, count %d, data 0x%p, physicalId %p", \ + __FUNCTION__, req, tag, count, data, physicalId); \ + return ACAMERA_ERROR_INVALID_PARAMETER; \ + } \ + if (req->physicalSettings.find(physicalId) == req->physicalSettings.end()) { \ + ALOGE("%s: Failed to find metadata for physical camera id %s", \ + __FUNCTION__, physicalId); \ + return ACAMERA_ERROR_INVALID_PARAMETER; \ + } \ + return req->physicalSettings[physicalId]->update(tag, count, data); \ +} + +SET_PHYSICAL_ENTRY(u8,uint8_t) +SET_PHYSICAL_ENTRY(i32,int32_t) +SET_PHYSICAL_ENTRY(float,float) +SET_PHYSICAL_ENTRY(double,double) +SET_PHYSICAL_ENTRY(i64,int64_t) +SET_PHYSICAL_ENTRY(rational,ACameraMetadata_rational) + +#undef SET_PHYSICAL_ENTRY + EXPORT void ACaptureRequest_free(ACaptureRequest* request) { ATRACE_CALL(); @@ -138,6 +187,7 @@ void ACaptureRequest_free(ACaptureRequest* request) { return; } request->settings.clear(); + request->physicalSettings.clear(); delete request->targets; delete request; return; @@ -174,6 +224,9 @@ ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src) { ACaptureRequest* pRequest = new ACaptureRequest(); pRequest->settings = new ACameraMetadata(*(src->settings)); + for (const auto& entry : src->physicalSettings) { + pRequest->physicalSettings[entry.first] = new ACameraMetadata(*(entry.second)); + } pRequest->targets = new ACameraOutputTargets(); *(pRequest->targets) = *(src->targets); pRequest->context = src->context; diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp index d8a57650c8..5e4fcd07fd 100644 --- a/camera/ndk/impl/ACameraDevice.cpp +++ b/camera/ndk/impl/ACameraDevice.cpp @@ -76,7 +76,7 @@ CameraDevice::CameraDevice( __FUNCTION__, strerror(-err), err); setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE); } - mHandler = new CallbackHandler(); + mHandler = new CallbackHandler(id); mCbLooper->registerHandler(mHandler); const CameraMetadata& metadata = mChars->getInternalData(); @@ -97,6 +97,14 @@ CameraDevice::CameraDevice( mShadingMapSize[0] = entry.data.i32[0]; mShadingMapSize[1] = entry.data.i32[1]; } + + size_t physicalIdCnt = 0; + const char*const* physicalCameraIds; + if (mChars->isLogicalMultiCamera(&physicalIdCnt, &physicalCameraIds)) { + for (size_t i = 0; i < physicalIdCnt; i++) { + mPhysicalIds.push_back(physicalCameraIds[i]); + } + } } // Device close implementaiton @@ -129,8 +137,29 @@ CameraDevice::postSessionMsgAndCleanup(sp& msg) { camera_status_t CameraDevice::createCaptureRequest( ACameraDevice_request_template templateId, + const ACameraIdList* physicalIdList, ACaptureRequest** request) const { Mutex::Autolock _l(mDeviceLock); + + if (physicalIdList != nullptr) { + if (physicalIdList->numCameras > static_cast(mPhysicalIds.size())) { + ALOGE("%s: physicalIdList size %d exceeds number of available physical cameras %zu", + __FUNCTION__, physicalIdList->numCameras, mPhysicalIds.size()); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + for (auto i = 0; i < physicalIdList->numCameras; i++) { + if (physicalIdList->cameraIds[i] == nullptr) { + ALOGE("%s: physicalId is null!", __FUNCTION__); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + if (mPhysicalIds.end() == std::find( + mPhysicalIds.begin(), mPhysicalIds.end(), physicalIdList->cameraIds[i])) { + ALOGE("%s: Invalid physicalId %s!", __FUNCTION__, physicalIdList->cameraIds[i]); + return ACAMERA_ERROR_INVALID_PARAMETER; + } + } + } + camera_status_t ret = checkCameraClosedOrErrorLocked(); if (ret != ACAMERA_OK) { return ret; @@ -151,6 +180,12 @@ CameraDevice::createCaptureRequest( } ACaptureRequest* outReq = new ACaptureRequest(); outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST); + if (physicalIdList != nullptr) { + for (auto i = 0; i < physicalIdList->numCameras; i++) { + outReq->physicalSettings.emplace(physicalIdList->cameraIds[i], + new ACameraMetadata(*(outReq->settings))); + } + } outReq->targets = new ACameraOutputTargets(); *request = outReq; return ACAMERA_OK; @@ -275,8 +310,12 @@ CameraDevice::allocateCaptureRequest( const ACaptureRequest* request, /*out*/sp& outReq) { camera_status_t ret; sp req(new CaptureRequest()); - req->mPhysicalCameraSettings.push_back({std::string(mCameraId.string()), + req->mPhysicalCameraSettings.push_back({getId(), request->settings->getInternalData()}); + for (auto& entry : request->physicalSettings) { + req->mPhysicalCameraSettings.push_back({entry.first, + entry.second->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 @@ -320,10 +359,17 @@ CameraDevice::allocateCaptureRequest( } ACaptureRequest* -CameraDevice::allocateACaptureRequest(sp& req) { +CameraDevice::allocateACaptureRequest(sp& req, const std::string& deviceId) { ACaptureRequest* pRequest = new ACaptureRequest(); - CameraMetadata clone = req->mPhysicalCameraSettings.begin()->settings; - pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST); + for (auto& entry : req->mPhysicalCameraSettings) { + CameraMetadata clone = entry.settings; + if (entry.id == deviceId) { + pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST); + } else { + pRequest->physicalSettings.emplace(entry.id, + new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST)); + } + } pRequest->targets = new ACameraOutputTargets(); for (size_t i = 0; i < req->mSurfaceList.size(); i++) { ANativeWindow* anw = static_cast(req->mSurfaceList[i].get()); @@ -340,6 +386,7 @@ CameraDevice::freeACaptureRequest(ACaptureRequest* req) { return; } req->settings.clear(); + req->physicalSettings.clear(); delete req->targets; delete req; } @@ -786,6 +833,9 @@ CameraDevice::onCaptureErrorLocked( return; } +CameraDevice::CallbackHandler::CallbackHandler(const char* id) : mId(id) { +} + void CameraDevice::CallbackHandler::onMessageReceived( const sp &msg) { switch (msg->what()) { @@ -927,7 +977,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( ALOGE("%s: Cannot find timestamp!", __FUNCTION__); return; } - ACaptureRequest* request = allocateACaptureRequest(requestSp); + ACaptureRequest* request = allocateACaptureRequest(requestSp, mId); (*onStart)(context, session.get(), request, timestamp); freeACaptureRequest(request); break; @@ -950,7 +1000,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( return; } sp result(static_cast(obj.get())); - ACaptureRequest* request = allocateACaptureRequest(requestSp); + ACaptureRequest* request = allocateACaptureRequest(requestSp, mId); (*onResult)(context, session.get(), request, result.get()); freeACaptureRequest(request); break; @@ -1006,7 +1056,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get()); } - ACaptureRequest* request = allocateACaptureRequest(requestSp); + ACaptureRequest* request = allocateACaptureRequest(requestSp, mId); (*onResult)(context, session.get(), request, result.get(), physicalResultInfo.size(), physicalCameraIdPtrs.data(), physicalMetadataCopyPtrs.data()); @@ -1034,7 +1084,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( static_cast(obj.get())); ACameraCaptureFailure* failure = static_cast(failureSp.get()); - ACaptureRequest* request = allocateACaptureRequest(requestSp); + ACaptureRequest* request = allocateACaptureRequest(requestSp, mId); (*onFail)(context, session.get(), request, failure); freeACaptureRequest(request); break; @@ -1111,7 +1161,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( return; } - ACaptureRequest* request = allocateACaptureRequest(requestSp); + ACaptureRequest* request = allocateACaptureRequest(requestSp, mId); (*onBufferLost)(context, session.get(), request, anw, frameNumber); freeACaptureRequest(request); break; diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h index d0f363bfbb..103efd5218 100644 --- a/camera/ndk/impl/ACameraDevice.h +++ b/camera/ndk/impl/ACameraDevice.h @@ -68,6 +68,7 @@ class CameraDevice final : public RefBase { camera_status_t createCaptureRequest( ACameraDevice_request_template templateId, + const ACameraIdList* physicalIdList, ACaptureRequest** request) const; camera_status_t createCaptureSession( @@ -145,7 +146,8 @@ class CameraDevice final : public RefBase { camera_status_t allocateCaptureRequest( const ACaptureRequest* request, sp& outReq); - static ACaptureRequest* allocateACaptureRequest(sp& req); + static ACaptureRequest* allocateACaptureRequest(sp& req, + const std::string& deviceId); static void freeACaptureRequest(ACaptureRequest*); // only For session to hold device lock @@ -230,9 +232,11 @@ class CameraDevice final : public RefBase { class CallbackHandler : public AHandler { public: + explicit CallbackHandler(const char* id); void onMessageReceived(const sp &msg) override; private: + std::string mId; // This handler will cache all capture session sp until kWhatCleanUpSessions // is processed. This is used to guarantee the last session reference is always // being removed in callback thread without holding camera device lock @@ -327,6 +331,7 @@ class CameraDevice final : public RefBase { // Misc variables int32_t mShadingMapSize[2]; // const after constructor int32_t mPartialResultCount; // const after constructor + std::vector mPhysicalIds; // const after constructor }; @@ -351,8 +356,9 @@ struct ACameraDevice { camera_status_t createCaptureRequest( ACameraDevice_request_template templateId, + const ACameraIdList* physicalCameraIdList, ACaptureRequest** request) const { - return mDevice->createCaptureRequest(templateId, request); + return mDevice->createCaptureRequest(templateId, physicalCameraIdList, request); } camera_status_t createCaptureSession( diff --git a/camera/ndk/impl/ACaptureRequest.h b/camera/ndk/impl/ACaptureRequest.h index 5c82ab7fa7..2ffcafecb2 100644 --- a/camera/ndk/impl/ACaptureRequest.h +++ b/camera/ndk/impl/ACaptureRequest.h @@ -18,6 +18,7 @@ #include #include +#include using namespace android; @@ -59,7 +60,8 @@ struct ACaptureRequest { return ACAMERA_OK; } - sp settings; + sp settings; + std::unordered_map> physicalSettings; ACameraOutputTargets* targets; void* context; }; diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h index 26af4f8787..cedf83a1a5 100644 --- a/camera/ndk/include/camera/NdkCameraDevice.h +++ b/camera/ndk/include/camera/NdkCameraDevice.h @@ -53,6 +53,17 @@ __BEGIN_DECLS */ typedef struct ACameraDevice ACameraDevice; +/** + * Struct to hold list of camera device Ids. This can refer to either the Ids + * of connected camera devices returned from {@link ACameraManager_getCameraIdList}, + * or the physical camera Ids passed into + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + */ +typedef struct ACameraIdList { + int numCameras; ///< Number of camera device Ids + const char** cameraIds; ///< list of camera device Ids +} ACameraIdList; + /// Enum for ACameraDevice_ErrorStateCallback error code enum { /** @@ -793,6 +804,47 @@ camera_status_t ACaptureSessionPhysicalOutput_create( ACameraWindowType* anw, const char* physicalId, /*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(29); +/** + * Create a logical multi-camera ACaptureRequest for capturing images, initialized with template + * for a target use case, with the ability to specify physical camera settings. + * + *

The settings are chosen to be the best options for this camera device, + * so it is not recommended to reuse the same request for a different camera device.

+ * + *

Note that for all keys in physical camera settings, only the keys + * advertised in ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS are + * applicable. All other keys are ignored by the camera device.

+ * + * @param device the camera device of interest + * @param templateId the type of capture request to be created. + * See {@link ACameraDevice_request_template}. + * @param physicalIdList The list of physical camera Ids that can be used to + * customize the request for a specific physical camera. + * @param request the output request will be stored here if the method call succeeds. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds. The created capture request will be + * filled in request argument.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if device, physicalIdList, or request is + * NULL, templateId is undefined or camera device does not support + * requested template, or if some Ids in physicalIdList isn't a + * valid physical camera backing the current camera device.
  • + *
  • {@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed.
  • + *
  • {@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error.
  • + *
  • {@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error.
  • + *
  • {@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.
+ * + * @see TEMPLATE_PREVIEW + * @see TEMPLATE_RECORD + * @see TEMPLATE_STILL_CAPTURE + * @see TEMPLATE_VIDEO_SNAPSHOT + * @see TEMPLATE_MANUAL + */ +camera_status_t ACameraDevice_createCaptureRequest_withPhysicalIds( + const ACameraDevice* device, ACameraDevice_request_template templateId, + const ACameraIdList* physicalIdList, + /*out*/ACaptureRequest** request) __INTRODUCED_IN(29); + #endif /* __ANDROID_API__ >= 29 */ __END_DECLS diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h index ea76738806..8d05ddb2a1 100644 --- a/camera/ndk/include/camera/NdkCameraManager.h +++ b/camera/ndk/include/camera/NdkCameraManager.h @@ -74,12 +74,6 @@ ACameraManager* ACameraManager_create() __INTRODUCED_IN(24); */ void ACameraManager_delete(ACameraManager* manager) __INTRODUCED_IN(24); -/// Struct to hold list of camera devices -typedef struct ACameraIdList { - int numCameras; ///< Number of connected camera devices - const char** cameraIds; ///< list of identifier of connected camera devices -} ACameraIdList; - /** * Create a list of currently connected camera devices, including * cameras that may be in use by other camera API clients. diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h index b200abf4e8..c26ca69efb 100644 --- a/camera/ndk/include/camera/NdkCameraMetadataTags.h +++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h @@ -3046,6 +3046,28 @@ typedef enum acamera_metadata_tag { */ ACAMERA_REQUEST_AVAILABLE_SESSION_KEYS = // int32[n] ACAMERA_REQUEST_START + 16, + /** + *

A subset of the available request keys that can be overridden for + * physical devices backing a logical multi-camera.

+ * + *

Type: int32[n]

+ * + *

This tag may appear in: + *

    + *
  • ACameraMetadata from ACameraManager_getCameraCharacteristics
  • + *

+ * + *

This is a subset of ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS which contains a list + * of keys that can be overridden using Builder#setPhysicalCameraKey. + * The respective value of such request key can be obtained by calling + * Builder#getPhysicalCameraKey. Capture requests that contain + * individual physical device requests must be built via + * Set).

+ * + * @see ACAMERA_REQUEST_AVAILABLE_REQUEST_KEYS + */ + ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS = // int32[n] + ACAMERA_REQUEST_START + 17, ACAMERA_REQUEST_END, /** diff --git a/camera/ndk/include/camera/NdkCaptureRequest.h b/camera/ndk/include/camera/NdkCaptureRequest.h index 136989a338..d3f8826002 100644 --- a/camera/ndk/include/camera/NdkCaptureRequest.h +++ b/camera/ndk/include/camera/NdkCaptureRequest.h @@ -358,6 +358,219 @@ ACaptureRequest* ACaptureRequest_copy(const ACaptureRequest* src) __INTRODUCED_I #endif /* __ANDROID_API__ >= 28 */ +#if __ANDROID_API__ >= 29 + +/** + * Get a metadata entry from input {@link ACaptureRequest} for + * a physical camera backing a logical multi-camera device. + * + *

Same as ACaptureRequest_getConstEntry, except that if the key is contained + * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function + * returns the entry set by ACaptureRequest_setEntry_physicalCamera_* class of + * functions on the particular physical camera.

+ * + * @param request the {@link ACaptureRequest} of interest created by + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param physicalId one of the physical Ids used when request is created with + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param tag the capture request metadata tag in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS} + * that is set by ACaptureRequest_setEntry_physicalCamera_* class of functions. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if metadata, physicalId, or entry is NULL, + * physicalId is not one of the Ids used in creating the request, or if the capture + * request is a regular request with no physical Ids at all.
  • + *
  • {@link ACAMERA_ERROR_METADATA_NOT_FOUND} if the capture request does not contain an + * entry of input tag value.
+ */ +camera_status_t ACaptureRequest_getConstEntry_physicalCamera( + const ACaptureRequest* request, const char* physicalId, uint32_t tag, + ACameraMetadata_const_entry* entry) __INTRODUCED_IN(29); + +/** + * Set/change a camera capture control entry with unsigned 8 bits data type for + * a physical camera backing a logical multi-camera device. + * + *

Same as ACaptureRequest_setEntry_u8, except that if {@link tag} is contained + * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function + * sets the entry for a particular physical sub-camera backing the logical multi-camera. + * If {@link tag} is not contained in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored + * by the camera device.

+ * + * @param request the {@link ACaptureRequest} of interest created by + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param physicalId one of the physical Ids used when request is created with + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param tag one of the capture request metadata tags in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is + * larger than zero while data is NULL, the data type of the tag is not unsigned 8 bits, + * the tag is not controllable by application, physicalId is not one of the Ids used + * in creating the request, or if the capture request is a regular request with no + * physical Ids at all.
+ */ +camera_status_t ACaptureRequest_setEntry_physicalCamera_u8( + ACaptureRequest* request, const char* physicalId, uint32_t tag, + uint32_t count, const uint8_t* data) __INTRODUCED_IN(29); + +/** + * Set/change a camera capture control entry with signed 32 bits data type for + * a physical camera of a logical multi-camera device. + * + *

Same as ACaptureRequest_setEntry_i32, except that if {@link tag} is contained + * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function + * sets the entry for a particular physical sub-camera backing the logical multi-camera. + * If {@link tag} is not contained in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored + * by the camera device.

+ * + * @param request the {@link ACaptureRequest} of interest created by + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param physicalId one of the physical Ids used when request is created with + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param tag one of the capture request metadata tags in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is + * larger than zero while data is NULL, the data type of the tag is not signed 32 bits, + * the tag is not controllable by application, physicalId is not one of the Ids used + * in creating the request, or if the capture request is a regular request with no + * physical Ids at all.
+ */ +camera_status_t ACaptureRequest_setEntry_physicalCamera_i32( + ACaptureRequest* request, const char* physicalId, uint32_t tag, + uint32_t count, const int32_t* data) __INTRODUCED_IN(29); + +/** + * Set/change a camera capture control entry with float data type for + * a physical camera of a logical multi-camera device. + * + *

Same as ACaptureRequest_setEntry_float, except that if {@link tag} is contained + * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function + * sets the entry for a particular physical sub-camera backing the logical multi-camera. + * If {@link tag} is not contained in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored + * by the camera device.

+ * + * @param request the {@link ACaptureRequest} of interest created by + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param physicalId one of the physical Ids used when request is created with + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param tag one of the capture request metadata tags in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is + * larger than zero while data is NULL, the data type of the tag is not float, + * the tag is not controllable by application, physicalId is not one of the Ids used + * in creating the request, or if the capture request is a regular request with no + * physical Ids at all.
+ */ +camera_status_t ACaptureRequest_setEntry_physicalCamera_float( + ACaptureRequest* request, const char* physicalId, uint32_t tag, + uint32_t count, const float* data) __INTRODUCED_IN(29); + +/** + * Set/change a camera capture control entry with signed 64 bits data type for + * a physical camera of a logical multi-camera device. + * + *

Same as ACaptureRequest_setEntry_i64, except that if {@link tag} is contained + * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function + * sets the entry for a particular physical sub-camera backing the logical multi-camera. + * If {@link tag} is not contained in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored + * by the camera device.

+ * + * @param request the {@link ACaptureRequest} of interest created by + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param physicalId one of the physical Ids used when request is created with + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param tag one of the capture request metadata tags in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is + * larger than zero while data is NULL, the data type of the tag is not signed 64 bits, + * the tag is not controllable by application, physicalId is not one of the Ids used + * in creating the request, or if the capture request is a regular request with no + * physical Ids at all.
+ */ +camera_status_t ACaptureRequest_setEntry_physicalCamera_i64( + ACaptureRequest* request, const char* physicalId, uint32_t tag, + uint32_t count, const int64_t* data) __INTRODUCED_IN(29); + +/** + * Set/change a camera capture control entry with double data type for + * a physical camera of a logical multi-camera device. + * + *

Same as ACaptureRequest_setEntry_double, except that if {@link tag} is contained + * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function + * sets the entry for a particular physical sub-camera backing the logical multi-camera. + * If {@link tag} is not contained in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored + * by the camera device.

+ * + * @param request the {@link ACaptureRequest} of interest created by + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param physicalId one of the physical Ids used when request is created with + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param tag one of the capture request metadata tags in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is + * larger than zero while data is NULL, the data type of the tag is not double, + * the tag is not controllable by application, physicalId is not one of the Ids used + * in creating the request, or if the capture request is a regular request with no + * physical Ids at all.
+ */ +camera_status_t ACaptureRequest_setEntry_physicalCamera_double( + ACaptureRequest* request, const char* physicalId, uint32_t tag, + uint32_t count, const double* data) __INTRODUCED_IN(29); + +/** + * Set/change a camera capture control entry with rational data type for + * a physical camera of a logical multi-camera device. + * + *

Same as ACaptureRequest_setEntry_rational, except that if {@link tag} is contained + * in {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, this function + * sets the entry for a particular physical sub-camera backing the logical multi-camera. + * If {@link tag} is not contained in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}, the key will be ignored + * by the camera device.

+ * + * @param request the {@link ACaptureRequest} of interest created by + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param physicalId one of the physical Ids used when request is created with + * {@link ACameraDevice_createCaptureRequest_withPhysicalIds}. + * @param tag one of the capture request metadata tags in + * {@link ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS}. + * + * @return
    + *
  • {@link ACAMERA_OK} if the method call succeeds.
  • + *
  • {@link ACAMERA_ERROR_INVALID_PARAMETER} if request or physicalId is NULL, count is + * larger than zero while data is NULL, the data type of the tag is not rational, + * the tag is not controllable by application, physicalId is not one of the Ids used + * in creating the request, or if the capture request is a regular request with no + * physical Ids at all.
+ */ +camera_status_t ACaptureRequest_setEntry_physicalCamera_rational( + ACaptureRequest* request, const char* physicalId, uint32_t tag, + uint32_t count, const ACameraMetadata_rational* data) __INTRODUCED_IN(29); + +#endif /* __ANDROID_API__ >= 29 */ + __END_DECLS #endif /* _NDK_CAPTURE_REQUEST_H */ diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt index 5a0002290a..2441830547 100644 --- a/camera/ndk/libcamera2ndk.map.txt +++ b/camera/ndk/libcamera2ndk.map.txt @@ -11,6 +11,7 @@ LIBCAMERA2NDK { ACameraCaptureSession_updateSharedOutput; # introduced=28 ACameraDevice_close; ACameraDevice_createCaptureRequest; + ACameraDevice_createCaptureRequest_withPhysicalIds; # introduced=29 ACameraDevice_createCaptureSession; ACameraDevice_createCaptureSessionWithSessionParameters; # introduced=28 ACameraDevice_getId; @@ -34,14 +35,21 @@ LIBCAMERA2NDK { ACaptureRequest_free; ACaptureRequest_getAllTags; ACaptureRequest_getConstEntry; + ACaptureRequest_getConstEntry_physicalCamera; # introduced=29 ACaptureRequest_getUserContext; # introduced=28 ACaptureRequest_removeTarget; ACaptureRequest_setEntry_double; + ACaptureRequest_setEntry_physicalCamera_double; # introduced=29 ACaptureRequest_setEntry_float; + ACaptureRequest_setEntry_physicalCamera_float; # introduced=29 ACaptureRequest_setEntry_i32; + ACaptureRequest_setEntry_physicalCamera_i32; # introduced=29 ACaptureRequest_setEntry_i64; + ACaptureRequest_setEntry_physicalCamera_i64; # introduced=29 ACaptureRequest_setEntry_rational; + ACaptureRequest_setEntry_physicalCamera_rational; # introduced=29 ACaptureRequest_setEntry_u8; + ACaptureRequest_setEntry_physicalCamera_u8; # introduced=29 ACaptureRequest_setUserContext; # introduced=28 ACaptureSessionOutputContainer_add; ACaptureSessionOutputContainer_create; diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp index 9aafcd3913..a38a31e79c 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp +++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp @@ -138,6 +138,7 @@ CameraDevice::postSessionMsgAndCleanup(sp& msg) { camera_status_t CameraDevice::createCaptureRequest( ACameraDevice_request_template templateId, + const ACameraIdList* physicalCameraIdList, ACaptureRequest** request) const { Mutex::Autolock _l(mDeviceLock); camera_status_t ret = checkCameraClosedOrErrorLocked(); @@ -168,6 +169,12 @@ CameraDevice::createCaptureRequest( } ACaptureRequest* outReq = new ACaptureRequest(); outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST); + if (physicalCameraIdList != nullptr) { + for (auto i = 0; i < physicalCameraIdList->numCameras; i++) { + outReq->physicalSettings.emplace(physicalCameraIdList->cameraIds[i], + new ACameraMetadata(*(outReq->settings))); + } + } outReq->targets = new ACameraOutputTargets(); *request = outReq; return ACAMERA_OK; @@ -292,29 +299,16 @@ camera_status_t CameraDevice::allocateCaptureRequestLocked( const ACaptureRequest* request, /*out*/sp &outReq) { sp req(new CaptureRequest()); - req->mCaptureRequest.physicalCameraSettings.resize(1); - req->mCaptureRequest.physicalCameraSettings[0].id = mCameraId; - // TODO: Do we really need to copy the metadata here ? - CameraMetadata metadataCopy = request->settings->getInternalData(); - const camera_metadata_t *cameraMetadata = metadataCopy.getAndLock(); - HCameraMetadata hCameraMetadata; - utils::convertToHidl(cameraMetadata, &hCameraMetadata); - metadataCopy.unlock(cameraMetadata); - if (request->settings != nullptr) { - if (hCameraMetadata.data() != nullptr && - mCaptureRequestMetadataQueue != nullptr && - mCaptureRequestMetadataQueue->write( - reinterpret_cast(hCameraMetadata.data()), - hCameraMetadata.size())) { - // The metadata field of the union would've been destructued, so no need - // to re-size it. - req->mCaptureRequest.physicalCameraSettings[0].settings.fmqMetadataSize( - hCameraMetadata.size()); - } else { - ALOGE("Fmq write capture result failed, falling back to hwbinder"); - req->mCaptureRequest.physicalCameraSettings[0].settings.metadata( - std::move(hCameraMetadata)); - } + req->mCaptureRequest.physicalCameraSettings.resize(1 + request->physicalSettings.size()); + + size_t index = 0; + allocateOneCaptureRequestMetadata( + req->mCaptureRequest.physicalCameraSettings[index++], mCameraId, request->settings); + + for (auto& physicalEntry : request->physicalSettings) { + allocateOneCaptureRequestMetadata( + req->mCaptureRequest.physicalCameraSettings[index++], + physicalEntry.first, physicalEntry.second); } std::vector requestStreamIdxList; @@ -356,13 +350,48 @@ CameraDevice::allocateCaptureRequestLocked( return ACAMERA_OK; } +void CameraDevice::allocateOneCaptureRequestMetadata( + PhysicalCameraSettings& cameraSettings, + const std::string& id, const sp& metadata) { + cameraSettings.id = id; + // TODO: Do we really need to copy the metadata here ? + CameraMetadata metadataCopy = metadata->getInternalData(); + const camera_metadata_t *cameraMetadata = metadataCopy.getAndLock(); + HCameraMetadata hCameraMetadata; + utils::convertToHidl(cameraMetadata, &hCameraMetadata); + metadataCopy.unlock(cameraMetadata); + if (metadata != nullptr) { + if (hCameraMetadata.data() != nullptr && + mCaptureRequestMetadataQueue != nullptr && + mCaptureRequestMetadataQueue->write( + reinterpret_cast(hCameraMetadata.data()), + hCameraMetadata.size())) { + // The metadata field of the union would've been destructued, so no need + // to re-size it. + cameraSettings.settings.fmqMetadataSize(hCameraMetadata.size()); + } else { + ALOGE("Fmq write capture result failed, falling back to hwbinder"); + cameraSettings.settings.metadata(std::move(hCameraMetadata)); + } + } +} + + ACaptureRequest* -CameraDevice::allocateACaptureRequest(sp& req) { +CameraDevice::allocateACaptureRequest(sp& req, const char* deviceId) { ACaptureRequest* pRequest = new ACaptureRequest(); - CameraMetadata clone; - utils::convertFromHidlCloned(req->mPhysicalCameraSettings[0].settings.metadata(), &clone); - pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST); - pRequest->targets = new ACameraOutputTargets(); + for (size_t i = 0; i < req->mPhysicalCameraSettings.size(); i++) { + const std::string& id = req->mPhysicalCameraSettings[i].id; + CameraMetadata clone; + utils::convertFromHidlCloned(req->mPhysicalCameraSettings[i].settings.metadata(), &clone); + if (id == deviceId) { + pRequest->settings = new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST); + } else { + pRequest->physicalSettings[req->mPhysicalCameraSettings[i].id] = + new ACameraMetadata(clone.release(), ACameraMetadata::ACM_REQUEST); + } + } + pRequest->targets = new ACameraOutputTargets(); for (size_t i = 0; i < req->mSurfaceList.size(); i++) { native_handle_t* anw = req->mSurfaceList[i]; ACameraOutputTarget outputTarget(anw); @@ -930,6 +959,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( return; } sp session(static_cast(obj.get())); + ACameraDevice* device = session->getDevice(); mCachedSessions.push(session); sp requestSp = nullptr; switch (msg->what()) { @@ -979,7 +1009,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( ALOGE("%s: Cannot find timestamp!", __FUNCTION__); return; } - ACaptureRequest* request = allocateACaptureRequest(requestSp); + ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId()); (*onStart)(context, session.get(), request, timestamp); freeACaptureRequest(request); break; @@ -1002,7 +1032,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( return; } sp result(static_cast(obj.get())); - ACaptureRequest* request = allocateACaptureRequest(requestSp); + ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId()); (*onResult)(context, session.get(), request, result.get()); freeACaptureRequest(request); break; @@ -1055,7 +1085,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get()); } - ACaptureRequest* request = allocateACaptureRequest(requestSp); + ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId()); (*onResult)(context, session.get(), request, result.get(), physicalResultInfo.size(), physicalCameraIdPtrs.data(), physicalMetadataCopyPtrs.data()); @@ -1084,7 +1114,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( static_cast(obj.get())); ACameraCaptureFailure* failure = static_cast(failureSp.get()); - ACaptureRequest* request = allocateACaptureRequest(requestSp); + ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId()); (*onFail)(context, session.get(), request, failure); freeACaptureRequest(request); break; @@ -1161,7 +1191,7 @@ void CameraDevice::CallbackHandler::onMessageReceived( return; } - ACaptureRequest* request = allocateACaptureRequest(requestSp); + ACaptureRequest* request = allocateACaptureRequest(requestSp, device->getId()); (*onBufferLost)(context, session.get(), request, anw, frameNumber); freeACaptureRequest(request); break; diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h index d5715854e9..28092fd373 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h +++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h @@ -92,6 +92,7 @@ class CameraDevice final : public RefBase { camera_status_t createCaptureRequest( ACameraDevice_request_template templateId, + const ACameraIdList* physicalCameraIdList, ACaptureRequest** request) const; camera_status_t createCaptureSession( @@ -176,8 +177,11 @@ class CameraDevice final : public RefBase { // metadata associated with it. camera_status_t allocateCaptureRequestLocked( const ACaptureRequest* request, sp& outReq); + void allocateOneCaptureRequestMetadata( + PhysicalCameraSettings& cameraSettings, + const std::string& id, const sp& metadata); - static ACaptureRequest* allocateACaptureRequest(sp& req); + static ACaptureRequest* allocateACaptureRequest(sp& req, const char* deviceId); static void freeACaptureRequest(ACaptureRequest*); // only For session to hold device lock @@ -380,8 +384,9 @@ struct ACameraDevice { camera_status_t createCaptureRequest( ACameraDevice_request_template templateId, + const ACameraIdList* physicalCameraIdList, ACaptureRequest** request) const { - return mDevice->createCaptureRequest(templateId, request); + return mDevice->createCaptureRequest(templateId, physicalCameraIdList, request); } camera_status_t createCaptureSession( diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp index 93108b0995..2398922048 100644 --- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp +++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp @@ -61,7 +61,8 @@ class CameraHelper { native_handle_t* anw; }; int initCamera(native_handle_t* imgReaderAnw, - const std::vector& physicalImgReaders) { + const std::vector& physicalImgReaders, + bool usePhysicalSettings) { if (imgReaderAnw == nullptr) { ALOGE("Cannot initialize camera before image reader get initialized."); return -1; @@ -97,6 +98,7 @@ class CameraHelper { return ret; } + std::vector idPointerList; for (auto& physicalStream : physicalImgReaders) { ACaptureSessionOutput* sessionOutput = nullptr; ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw, @@ -113,7 +115,11 @@ class CameraHelper { mExtraOutputs.push_back(sessionOutput); // Assume that at most one physical stream per physical camera. mPhysicalCameraIds.push_back(physicalStream.physicalCameraId); + idPointerList.push_back(physicalStream.physicalCameraId); } + ACameraIdList cameraIdList; + cameraIdList.numCameras = idPointerList.size(); + cameraIdList.cameraIds = idPointerList.data(); ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession); if (ret != AMEDIA_OK) { @@ -122,7 +128,13 @@ class CameraHelper { } // Create capture request - ret = ACameraDevice_createCaptureRequest(mDevice, TEMPLATE_STILL_CAPTURE, &mStillRequest); + if (usePhysicalSettings) { + ret = ACameraDevice_createCaptureRequest_withPhysicalIds(mDevice, + TEMPLATE_STILL_CAPTURE, &cameraIdList, &mStillRequest); + } else { + ret = ACameraDevice_createCaptureRequest(mDevice, + TEMPLATE_STILL_CAPTURE, &mStillRequest); + } if (ret != AMEDIA_OK) { ALOGE("ACameraDevice_createCaptureRequest failed, ret=%d", ret); return ret; @@ -557,7 +569,8 @@ class AImageReaderVendorTest : public ::testing::Test { } CameraHelper cameraHelper(id, mCameraManager); - ret = cameraHelper.initCamera(testCase.getNativeWindow(), {}); + ret = cameraHelper.initCamera(testCase.getNativeWindow(), + {}/*physicalImageReaders*/, false/*usePhysicalSettings*/); if (ret < 0) { ALOGE("Unable to initialize camera helper"); return false; @@ -695,6 +708,69 @@ class AImageReaderVendorTest : public ::testing::Test { *cameraId = nullptr; return; } + + void testLogicalCameraPhysicalStream(bool usePhysicalSettings) { + const char* cameraId = nullptr; + ACameraMetadata* staticMetadata = nullptr; + std::vector physicalCameraIds; + + findCandidateLogicalCamera(&cameraId, &staticMetadata, &physicalCameraIds); + if (cameraId == nullptr) { + // Couldn't find logical camera to test + return; + } + + // Test streaming the logical multi-camera + uint64_t readerUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN; + int32_t readerMaxImages = 8; + bool readerAsync = false; + const int pictureCount = 6; + std::vector testCases; + for (size_t i = 0; i < 3; i++) { + ImageReaderTestCase* testCase = new ImageReaderTestCase( + kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, + readerMaxImages, readerAsync); + ASSERT_EQ(testCase->initImageReader(), 0); + testCases.push_back(testCase); + } + + CameraHelper cameraHelper(cameraId, mCameraManager); + std::vector physicalImgReaderInfo; + physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()}); + physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()}); + + int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(), + physicalImgReaderInfo, usePhysicalSettings); + ASSERT_EQ(ret, 0); + + if (!cameraHelper.isCameraReady()) { + ALOGW("Camera is not ready after successful initialization. It's either due to camera " + "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have " + "camera on board."); + return; + } + + for (int i = 0; i < pictureCount; i++) { + ret = cameraHelper.takeLogicalCameraPicture(); + ASSERT_EQ(ret, 0); + } + + // Sleep until all capture finished + for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) { + usleep(kCaptureWaitUs); + if (testCases[0]->getAcquiredImageCount() == pictureCount) { + ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000, + pictureCount); + break; + } + } + ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount); + ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount); + ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount); + ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount)); + + ACameraMetadata_free(staticMetadata); + } }; TEST_F(AImageReaderVendorTest, CreateWindowNativeHandle) { @@ -722,65 +798,8 @@ TEST_F(AImageReaderVendorTest, CreateWindowNativeHandle) { } TEST_F(AImageReaderVendorTest, LogicalCameraPhysicalStream) { - const char* cameraId = nullptr; - ACameraMetadata* staticMetadata = nullptr; - std::vector physicalCameraIds; - - findCandidateLogicalCamera(&cameraId, &staticMetadata, &physicalCameraIds); - if (cameraId == nullptr) { - // Couldn't find logical camera to test - return; - } - - // Test streaming the logical multi-camera - uint64_t readerUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN; - int32_t readerMaxImages = 8; - bool readerAsync = false; - const int pictureCount = 6; - std::vector testCases; - for (size_t i = 0; i < 3; i++) { - ImageReaderTestCase* testCase = new ImageReaderTestCase( - kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages, - readerAsync); - ASSERT_EQ(testCase->initImageReader(), 0); - testCases.push_back(testCase); - } - - CameraHelper cameraHelper(cameraId, mCameraManager); - std::vector physicalImgReaderInfo; - physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()}); - physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()}); - - int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo); - ASSERT_EQ(ret, 0); - - if (!cameraHelper.isCameraReady()) { - ALOGW("Camera is not ready after successful initialization. It's either due to camera on " - "board lacks BACKWARDS_COMPATIBLE capability or the device does not have camera on " - "board."); - return; - } - - for (int i = 0; i < pictureCount; i++) { - ret = cameraHelper.takeLogicalCameraPicture(); - ASSERT_EQ(ret, 0); - } - - // Sleep until all capture finished - for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) { - usleep(kCaptureWaitUs); - if (testCases[0]->getAcquiredImageCount() == pictureCount) { - ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000, - pictureCount); - break; - } - } - ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount); - ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount); - ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount); - ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount)); - - ACameraMetadata_free(staticMetadata); + testLogicalCameraPhysicalStream(false/*usePhysicalSettings*/); + testLogicalCameraPhysicalStream(true/*usePhysicalSettings*/); } } // namespace