Camera: Enable logical multi-camera API in NDK
The support inclues:
- Physical camera specific stream support,
- Physical camera result metadata, and
Test: Newly added NDK CTS test pass
Test: Newly added VNDK test pass
Bug: 120566141
Bug: 115532726
Change-Id: I939b81522ca6c518c0e54ded5d3615f9973a6a65
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 321eb08..4e9b27d 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -167,19 +167,23 @@
}
OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
+ const String16& physicalId,
int surfaceSetID, bool isShared) {
mGbps.push_back(gbp);
mRotation = rotation;
mSurfaceSetID = surfaceSetID;
mIsDeferred = false;
mIsShared = isShared;
+ mPhysicalCameraId = physicalId;
}
OutputConfiguration::OutputConfiguration(
const std::vector<sp<IGraphicBufferProducer>>& gbps,
- int rotation, int surfaceSetID, int surfaceType, int width, int height, bool isShared)
+ int rotation, const String16& physicalCameraId, int surfaceSetID, int surfaceType,
+ int width, int height, bool isShared)
: mGbps(gbps), mRotation(rotation), mSurfaceSetID(surfaceSetID), mSurfaceType(surfaceType),
- mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared) { }
+ mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared),
+ mPhysicalCameraId(physicalCameraId) { }
status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 5b117fb..95c4f39 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -65,10 +65,12 @@
OutputConfiguration(const android::Parcel& parcel);
OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
+ const String16& physicalCameraId,
int surfaceSetID = INVALID_SET_ID, bool isShared = false);
OutputConfiguration(const std::vector<sp<IGraphicBufferProducer>>& gbps,
- int rotation, int surfaceSetID = INVALID_SET_ID,
+ int rotation, const String16& physicalCameraId,
+ int surfaceSetID = INVALID_SET_ID,
int surfaceType = OutputConfiguration::SURFACE_TYPE_UNKNOWN, int width = 0,
int height = 0, bool isShared = false);
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index fd95296..540d84e 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -28,6 +28,8 @@
#include <camera/NdkCameraCaptureSession.h>
#include "impl/ACameraCaptureSession.h"
+#include "impl/ACameraCaptureSession.inc"
+
using namespace android;
EXPORT
@@ -82,7 +84,31 @@
return ACAMERA_ERROR_SESSION_CLOSED;
}
- return session->capture(cbs, numRequests, requests, captureSequenceId);
+ return session->capture(
+ cbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
+camera_status_t ACameraCaptureSession_logicalCamera_capture(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ if (session == nullptr || requests == nullptr || numRequests < 1) {
+ ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+ __FUNCTION__, session, numRequests, requests);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ return session->capture(
+ lcbs, numRequests, requests, captureSequenceId);
}
EXPORT
@@ -107,6 +133,28 @@
}
EXPORT
+camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ ATRACE_CALL();
+ if (session == nullptr || requests == nullptr || numRequests < 1) {
+ ALOGE("%s: Error: invalid input: session %p, numRequest %d, requests %p",
+ __FUNCTION__, session, numRequests, requests);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (session->isClosed()) {
+ ALOGE("%s: session %p is already closed", __FUNCTION__, session);
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ return session->setRepeatingRequest(lcbs, numRequests, requests, captureSequenceId);
+}
+
+EXPORT
camera_status_t ACameraCaptureSession_stopRepeating(ACameraCaptureSession* session) {
ATRACE_CALL();
if (session == nullptr) {
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index ef05e0b..98608da 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -129,6 +129,20 @@
}
EXPORT
+camera_status_t ACaptureSessionPhysicalOutput_create(
+ ACameraWindowType* window, const char* physicalId,
+ /*out*/ACaptureSessionOutput** out) {
+ ATRACE_CALL();
+ if (window == nullptr || physicalId == nullptr || out == nullptr) {
+ ALOGE("%s: Error: bad argument. window %p, physicalId %p, out %p",
+ __FUNCTION__, window, physicalId, out);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ *out = new ACaptureSessionOutput(window, false, physicalId);
+ return ACAMERA_OK;
+}
+
+EXPORT
camera_status_t ACaptureSessionSharedOutput_add(ACaptureSessionOutput *out,
ACameraWindowType* window) {
ATRACE_CALL();
diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp
index 34ec2da..9a39ed8 100644
--- a/camera/ndk/NdkCameraMetadata.cpp
+++ b/camera/ndk/NdkCameraMetadata.cpp
@@ -69,3 +69,20 @@
metadata->decStrong((void*) ACameraMetadata_free);
}
}
+
+EXPORT
+bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,
+ /*out*/size_t* numPhysicalCameras, /*out*/const char*const** physicalCameraIds) {
+ ATRACE_CALL();
+ if (numPhysicalCameras == nullptr || physicalCameraIds == nullptr) {
+ ALOGE("%s: Invalid input: numPhysicalCameras %p, physicalCameraIds %p",
+ __FUNCTION__, numPhysicalCameras, physicalCameraIds);
+ return false;
+ }
+ if (staticMetadata == nullptr) {
+ ALOGE("%s: Invalid input: staticMetadata is null.", __FUNCTION__);
+ return false;
+ }
+
+ return staticMetadata->isLogicalMultiCamera(numPhysicalCameras, physicalCameraIds);
+}
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
index fb72bdb..d6f1412 100644
--- a/camera/ndk/impl/ACameraCaptureSession.cpp
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -107,47 +107,6 @@
return ret;
}
-camera_status_t
-ACameraCaptureSession::setRepeatingRequest(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- sp<acam::CameraDevice> dev = getDeviceSp();
- if (dev == nullptr) {
- ALOGE("Error: Device associated with session %p has been closed!", this);
- return ACAMERA_ERROR_SESSION_CLOSED;
- }
-
- camera_status_t ret;
- dev->lockDeviceForSessionOps();
- {
- Mutex::Autolock _l(mSessionLock);
- ret = dev->setRepeatingRequestsLocked(
- this, cbs, numRequests, requests, captureSequenceId);
- }
- dev->unlockDevice();
- return ret;
-}
-
-camera_status_t ACameraCaptureSession::capture(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- sp<acam::CameraDevice> dev = getDeviceSp();
- if (dev == nullptr) {
- ALOGE("Error: Device associated with session %p has been closed!", this);
- return ACAMERA_ERROR_SESSION_CLOSED;
- }
- camera_status_t ret;
- dev->lockDeviceForSessionOps();
- {
- Mutex::Autolock _l(mSessionLock);
- ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
- }
- dev->unlockDevice();
- return ret;
-}
-
camera_status_t ACameraCaptureSession::updateOutputConfiguration(ACaptureSessionOutput *output) {
sp<acam::CameraDevice> dev = getDeviceSp();
if (dev == nullptr) {
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
index 133c2c8..08a9226 100644
--- a/camera/ndk/impl/ACameraCaptureSession.h
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -17,6 +17,7 @@
#define _ACAMERA_CAPTURE_SESSION_H
#include <set>
+#include <string>
#include <hardware/camera3.h>
#include <camera/NdkCameraDevice.h>
@@ -29,8 +30,9 @@
using namespace android;
struct ACaptureSessionOutput {
- explicit ACaptureSessionOutput(ACameraWindowType* window, bool isShared = false) :
- mWindow(window), mIsShared(isShared) {};
+ explicit ACaptureSessionOutput(ACameraWindowType* window, bool isShared = false,
+ const char* physicalCameraId = "") :
+ mWindow(window), mIsShared(isShared), mPhysicalCameraId(physicalCameraId) {};
bool operator == (const ACaptureSessionOutput& other) const {
return mWindow == other.mWindow;
@@ -49,6 +51,7 @@
std::set<ACameraWindowType *> mSharedWindows;
bool mIsShared;
int mRotation = CAMERA3_STREAM_ROTATION_0;
+ std::string mPhysicalCameraId;
};
#endif
@@ -88,13 +91,15 @@
camera_status_t abortCaptures();
+ template<class T>
camera_status_t setRepeatingRequest(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template<class T>
camera_status_t capture(
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
diff --git a/camera/ndk/impl/ACameraCaptureSession.inc b/camera/ndk/impl/ACameraCaptureSession.inc
new file mode 100644
index 0000000..86bf8a5
--- /dev/null
+++ b/camera/ndk/impl/ACameraCaptureSession.inc
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ACameraCaptureSession.h"
+
+#ifdef __ANDROID_VNDK__
+#include "ndk_vendor/impl/ACameraDeviceVendor.inc"
+#else
+#include "ACameraDevice.inc"
+#endif
+
+using namespace android;
+
+template <class T>
+camera_status_t
+ACameraCaptureSession::setRepeatingRequest(
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ sp<acam::CameraDevice> dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->setRepeatingRequestsLocked(
+ this, cbs, numRequests, requests, captureSequenceId);
+ }
+ dev->unlockDevice();
+ return ret;
+}
+
+template <class T>
+camera_status_t ACameraCaptureSession::capture(
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ sp<acam::CameraDevice> dev = getDeviceSp();
+ if (dev == nullptr) {
+ ALOGE("Error: Device associated with session %p has been closed!", this);
+ return ACAMERA_ERROR_SESSION_CLOSED;
+ }
+ camera_status_t ret;
+ dev->lockDeviceForSessionOps();
+ {
+ Mutex::Autolock _l(mSessionLock);
+ ret = dev->captureLocked(this, cbs, numRequests, requests, captureSequenceId);
+ }
+ dev->unlockDevice();
+ return ret;
+}
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 657d41f..d8a5765 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -20,13 +20,14 @@
#include <vector>
#include <inttypes.h>
#include <android/hardware/ICameraService.h>
-#include <camera2/SubmitInfo.h>
#include <gui/Surface.h>
#include "ACameraDevice.h"
#include "ACameraMetadata.h"
#include "ACaptureRequest.h"
#include "ACameraCaptureSession.h"
+#include "ACameraCaptureSession.inc"
+
namespace android {
namespace acam {
@@ -39,6 +40,7 @@
const char* CameraDevice::kCaptureRequestKey = "CaptureRequest";
const char* CameraDevice::kTimeStampKey = "TimeStamp";
const char* CameraDevice::kCaptureResultKey = "CaptureResult";
+const char* CameraDevice::kPhysicalCaptureResultKey = "PhysicalCaptureResult";
const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
const char* CameraDevice::kSequenceIdKey = "SequenceId";
const char* CameraDevice::kFrameNumberKey = "FrameNumber";
@@ -190,106 +192,6 @@
return ACAMERA_OK;
}
-camera_status_t
-CameraDevice::captureLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- return submitRequestsLocked(
- session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
-}
-
-camera_status_t
-CameraDevice::setRepeatingRequestsLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- return submitRequestsLocked(
- session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
-}
-
-camera_status_t
-CameraDevice::submitRequestsLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId,
- bool isRepeating) {
- camera_status_t ret = checkCameraClosedOrErrorLocked();
- if (ret != ACAMERA_OK) {
- ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
- return ret;
- }
-
- // Form two vectors of capture request, one for internal tracking
- std::vector<hardware::camera2::CaptureRequest> requestList;
- Vector<sp<CaptureRequest> > requestsV;
- requestsV.setCapacity(numRequests);
- for (int i = 0; i < numRequests; i++) {
- sp<CaptureRequest> req;
- ret = allocateCaptureRequest(requests[i], req);
- if (ret != ACAMERA_OK) {
- ALOGE("Convert capture request to internal format failure! ret %d", ret);
- return ret;
- }
- if (req->mSurfaceList.empty()) {
- ALOGE("Capture request without output target cannot be submitted!");
- return ACAMERA_ERROR_INVALID_PARAMETER;
- }
- requestList.push_back(*(req.get()));
- requestsV.push_back(req);
- }
-
- if (isRepeating) {
- ret = stopRepeatingLocked();
- if (ret != ACAMERA_OK) {
- ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
- return ret;
- }
- }
-
- binder::Status remoteRet;
- hardware::camera2::utils::SubmitInfo info;
- remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
- int sequenceId = info.mRequestId;
- int64_t lastFrameNumber = info.mLastFrameNumber;
- if (sequenceId < 0) {
- ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
- return ACAMERA_ERROR_UNKNOWN;
- }
-
- CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
- mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
-
- if (isRepeating) {
- // stopRepeating above should have cleanup repeating sequence id
- if (mRepeatingSequenceId != REQUEST_ID_NONE) {
- setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
- return ACAMERA_ERROR_CAMERA_DEVICE;
- }
- mRepeatingSequenceId = sequenceId;
- } else {
- mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
- }
-
- if (mIdle) {
- sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
- msg->setPointer(kContextKey, session->mUserSessionCallback.context);
- msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
- postSessionMsgAndCleanup(msg);
- }
- mIdle = false;
- mBusySession = session;
-
- if (captureSequenceId) {
- *captureSequenceId = sequenceId;
- }
- return ACAMERA_OK;
-}
-
camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) {
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
@@ -325,8 +227,9 @@
return ret;
}
- OutputConfiguration outConfig(iGBP, output->mRotation, OutputConfiguration::INVALID_SET_ID,
- true);
+ String16 physicalId16(output->mPhysicalCameraId.c_str());
+ OutputConfiguration outConfig(iGBP, output->mRotation, physicalId16,
+ OutputConfiguration::INVALID_SET_ID, true);
for (auto& anw : output->mSharedWindows) {
ret = getIGBPfromAnw(anw, iGBP);
@@ -640,8 +543,9 @@
if (ret != ACAMERA_OK) {
return ret;
}
+ String16 physicalId16(outConfig.mPhysicalCameraId.c_str());
outputSet.insert(std::make_pair(
- anw, OutputConfiguration(iGBP, outConfig.mRotation,
+ anw, OutputConfiguration(iGBP, outConfig.mRotation, physicalId16,
OutputConfiguration::INVALID_SET_ID, outConfig.mIsShared)));
}
auto addSet = outputSet;
@@ -829,7 +733,7 @@
if (errorCode == hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER) {
int32_t streamId = resultExtras.errorStreamId;
ACameraCaptureSession_captureCallback_bufferLost onBufferLost =
- cbh.mCallbacks.onCaptureBufferLost;
+ cbh.mOnCaptureBufferLost;
auto outputPairIt = mConfiguredOutputs.find(streamId);
if (outputPairIt == mConfiguredOutputs.end()) {
ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId);
@@ -846,7 +750,7 @@
getId(), anw, frameNumber);
sp<AMessage> msg = new AMessage(kWhatCaptureBufferLost, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onBufferLost);
msg->setObject(kCaptureRequestKey, request);
@@ -858,7 +762,7 @@
}
} else { // Handle other capture failures
// Fire capture failure callback if there is one registered
- ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
+ ACameraCaptureSession_captureCallback_failed onError = cbh.mOnCaptureFailed;
sp<CameraCaptureFailure> failure(new CameraCaptureFailure());
failure->frameNumber = frameNumber;
// TODO: refine this when implementing flush
@@ -868,7 +772,7 @@
hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT);
sp<AMessage> msg = new AMessage(kWhatCaptureFail, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onError);
msg->setObject(kCaptureRequestKey, request);
@@ -890,6 +794,7 @@
case kWhatSessionStateCb:
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
@@ -960,6 +865,7 @@
case kWhatSessionStateCb:
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
@@ -977,6 +883,7 @@
switch (msg->what()) {
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureBufferLost:
found = msg->findObject(kCaptureRequestKey, &obj);
@@ -1048,6 +955,64 @@
freeACaptureRequest(request);
break;
}
+ case kWhatLogicalCaptureResult:
+ {
+ ACameraCaptureSession_logicalCamera_captureCallback_result onResult;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+ if (!found) {
+ ALOGE("%s: Cannot find logicalCamera capture result callback!",
+ __FUNCTION__);
+ return;
+ }
+ if (onResult == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+ return;
+ }
+ sp<ACameraMetadata> result(static_cast<ACameraMetadata*>(obj.get()));
+
+ found = msg->findObject(kPhysicalCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find physical capture result!", __FUNCTION__);
+ return;
+ }
+ sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+ static_cast<ACameraPhysicalCaptureResultInfo*>(obj.get()));
+ std::vector<PhysicalCaptureResultInfo>& physicalResultInfo =
+ physicalResult->mPhysicalResultInfo;
+
+ std::vector<std::string> physicalCameraIds;
+ std::vector<sp<ACameraMetadata>> physicalMetadataCopy;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ String8 physicalId8(physicalResultInfo[i].mPhysicalCameraId);
+ physicalCameraIds.push_back(physicalId8.c_str());
+
+ CameraMetadata clone = physicalResultInfo[i].mPhysicalCameraMetadata;
+ clone.update(ANDROID_SYNC_FRAME_NUMBER,
+ &physicalResult->mFrameNumber, /*data_count*/1);
+ sp<ACameraMetadata> metadata =
+ new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT);
+ physicalMetadataCopy.push_back(metadata);
+ }
+
+ std::vector<const char*> physicalCameraIdPtrs;
+ std::vector<const ACameraMetadata*> physicalMetadataCopyPtrs;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ physicalCameraIdPtrs.push_back(physicalCameraIds[i].c_str());
+ physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get());
+ }
+
+ ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ (*onResult)(context, session.get(), request, result.get(),
+ physicalResultInfo.size(), physicalCameraIdPtrs.data(),
+ physicalMetadataCopyPtrs.data());
+ freeACaptureRequest(request);
+ break;
+ }
case kWhatCaptureFail:
{
ACameraCaptureSession_captureCallback_failed onFail;
@@ -1158,12 +1123,34 @@
}
CameraDevice::CallbackHolder::CallbackHolder(
- sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest> >& requests,
- bool isRepeating,
- ACameraCaptureSession_captureCallbacks* cbs) :
- mSession(session), mRequests(requests),
- mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {}
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacks* cbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(false) {
+ initCaptureCallbacks(cbs);
+
+ if (cbs != nullptr) {
+ mOnCaptureCompleted = cbs->onCaptureCompleted;
+ }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(true) {
+ initCaptureCallbacks(lcbs);
+
+ if (lcbs != nullptr) {
+ mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted;
+ }
+}
void
CameraDevice::checkRepeatingSequenceCompleteLocked(
@@ -1180,9 +1167,9 @@
mSequenceCallbackMap.erase(cbIt);
// send seq aborted callback
sp<AMessage> msg = new AMessage(kWhatCaptureSeqAbort, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceAborted);
msg->setInt32(kSequenceIdKey, sequenceId);
postSessionMsgAndCleanup(msg);
} else {
@@ -1230,9 +1217,9 @@
mSequenceCallbackMap.erase(cbIt);
// send seq complete callback
sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
msg->setInt32(kSequenceIdKey, sequenceId);
msg->setInt64(kFrameNumberKey, lastFrameNumber);
@@ -1389,7 +1376,7 @@
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted;
+ ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1398,7 +1385,7 @@
}
sp<CaptureRequest> request = cbh.mRequests[burstId];
sp<AMessage> msg = new AMessage(kWhatCaptureStart, dev->mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onStart);
msg->setObject(kCaptureRequestKey, request);
@@ -1413,7 +1400,6 @@
const CameraMetadata& metadata,
const CaptureResultExtras& resultExtras,
const std::vector<PhysicalCaptureResultInfo>& physicalResultInfos) {
- (void) physicalResultInfos;
binder::Status ret = binder::Status::ok();
sp<CameraDevice> dev = mDevice.promote();
@@ -1449,9 +1435,6 @@
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_result onResult = isPartialResult ?
- cbh.mCallbacks.onCaptureProgressed :
- cbh.mCallbacks.onCaptureCompleted;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1461,13 +1444,27 @@
sp<CaptureRequest> request = cbh.mRequests[burstId];
sp<ACameraMetadata> result(new ACameraMetadata(
metadataCopy.release(), ACameraMetadata::ACM_RESULT));
+ sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+ new ACameraPhysicalCaptureResultInfo(physicalResultInfos, frameNumber));
- sp<AMessage> msg = new AMessage(kWhatCaptureResult, dev->mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ sp<AMessage> msg = new AMessage(
+ cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureResult : kWhatCaptureResult,
+ dev->mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) onResult);
msg->setObject(kCaptureRequestKey, request);
msg->setObject(kCaptureResultKey, result);
+ if (isPartialResult) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureProgressed);
+ } else if (cbh.mIsLogicalCameraCallback) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnLogicalCameraCaptureCompleted);
+ msg->setObject(kPhysicalCaptureResultKey, physicalResult);
+ } else {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureCompleted);
+ }
dev->postSessionMsgAndCleanup(msg);
}
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 8f56d3f..d0f363b 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -21,6 +21,7 @@
#include <set>
#include <atomic>
#include <utility>
+#include <vector>
#include <utils/StrongPointer.h>
#include <utils/Mutex.h>
#include <utils/String8.h>
@@ -46,6 +47,16 @@
// Wrap ACameraCaptureFailure so it can be ref-counted
struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure {};
+// Wrap PhysicalCaptureResultInfo so that it can be ref-counted
+struct ACameraPhysicalCaptureResultInfo: public RefBase {
+ ACameraPhysicalCaptureResultInfo(const std::vector<PhysicalCaptureResultInfo>& info,
+ int64_t frameNumber) :
+ mPhysicalResultInfo(info), mFrameNumber(frameNumber) {}
+
+ std::vector<PhysicalCaptureResultInfo> mPhysicalResultInfo;
+ int64_t mFrameNumber;
+};
+
class CameraDevice final : public RefBase {
public:
CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
@@ -109,19 +120,22 @@
camera_status_t waitUntilIdleLocked();
+ template<class T>
camera_status_t captureLocked(sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template<class T>
camera_status_t setRepeatingRequestsLocked(sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template<class T>
camera_status_t submitRequestsLocked(
sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*out*/int* captureSequenceId,
bool isRepeating);
@@ -192,6 +206,7 @@
// Capture callbacks
kWhatCaptureStart, // onCaptureStarted
kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
+ kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted
kWhatCaptureFail, // onCaptureFailed
kWhatCaptureSeqEnd, // onCaptureSequenceCompleted
kWhatCaptureSeqAbort, // onCaptureSequenceAborted
@@ -207,6 +222,7 @@
static const char* kCaptureRequestKey;
static const char* kTimeStampKey;
static const char* kCaptureResultKey;
+ static const char* kPhysicalCaptureResultKey;
static const char* kCaptureFailureKey;
static const char* kSequenceIdKey;
static const char* kFrameNumberKey;
@@ -245,19 +261,46 @@
const Vector<sp<CaptureRequest> >& requests,
bool isRepeating,
ACameraCaptureSession_captureCallbacks* cbs);
+ CallbackHolder(sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
- static ACameraCaptureSession_captureCallbacks fillCb(
- ACameraCaptureSession_captureCallbacks* cbs) {
+ template <class T>
+ void initCaptureCallbacks(T* cbs) {
+ mContext = nullptr;
+ mOnCaptureStarted = nullptr;
+ mOnCaptureProgressed = nullptr;
+ mOnCaptureCompleted = nullptr;
+ mOnLogicalCameraCaptureCompleted = nullptr;
+ mOnCaptureFailed = nullptr;
+ mOnCaptureSequenceCompleted = nullptr;
+ mOnCaptureSequenceAborted = nullptr;
+ mOnCaptureBufferLost = nullptr;
if (cbs != nullptr) {
- return *cbs;
+ mContext = cbs->context;
+ mOnCaptureStarted = cbs->onCaptureStarted;
+ mOnCaptureProgressed = cbs->onCaptureProgressed;
+ mOnCaptureFailed = cbs->onCaptureFailed;
+ mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted;
+ mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted;
+ mOnCaptureBufferLost = cbs->onCaptureBufferLost;
}
- return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
}
-
sp<ACameraCaptureSession> mSession;
Vector<sp<CaptureRequest> > mRequests;
const bool mIsRepeating;
- ACameraCaptureSession_captureCallbacks mCallbacks;
+ const bool mIsLogicalCameraCallback;
+
+ void* mContext;
+ ACameraCaptureSession_captureCallback_start mOnCaptureStarted;
+ ACameraCaptureSession_captureCallback_result mOnCaptureProgressed;
+ ACameraCaptureSession_captureCallback_result mOnCaptureCompleted;
+ ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted;
+ ACameraCaptureSession_captureCallback_failed mOnCaptureFailed;
+ ACameraCaptureSession_captureCallback_sequenceEnd mOnCaptureSequenceCompleted;
+ ACameraCaptureSession_captureCallback_sequenceAbort mOnCaptureSequenceAborted;
+ ACameraCaptureSession_captureCallback_bufferLost mOnCaptureBufferLost;
};
// sequence id -> callbacks map
std::map<int, CallbackHolder> mSequenceCallbackMap;
diff --git a/camera/ndk/impl/ACameraDevice.inc b/camera/ndk/impl/ACameraDevice.inc
new file mode 100644
index 0000000..1fc5352
--- /dev/null
+++ b/camera/ndk/impl/ACameraDevice.inc
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vector>
+#include <inttypes.h>
+#include "ACameraDevice.h"
+#include "ACameraMetadata.h"
+#include "ACaptureRequest.h"
+#include "ACameraCaptureSession.h"
+
+namespace android {
+namespace acam {
+
+template<class T>
+camera_status_t
+CameraDevice::captureLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
+}
+
+template<class T>
+camera_status_t
+CameraDevice::setRepeatingRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
+}
+
+template<class T>
+camera_status_t CameraDevice::submitRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId,
+ bool isRepeating) {
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
+ return ret;
+ }
+
+ // Form two vectors of capture request, one for internal tracking
+ std::vector<hardware::camera2::CaptureRequest> requestList;
+ Vector<sp<CaptureRequest> > requestsV;
+ requestsV.setCapacity(numRequests);
+ for (int i = 0; i < numRequests; i++) {
+ sp<CaptureRequest> req;
+ ret = allocateCaptureRequest(requests[i], req);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Convert capture request to internal format failure! ret %d", ret);
+ return ret;
+ }
+ if (req->mSurfaceList.empty()) {
+ ALOGE("Capture request without output target cannot be submitted!");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ requestList.push_back(*(req.get()));
+ requestsV.push_back(req);
+ }
+
+ if (isRepeating) {
+ ret = stopRepeatingLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+ return ret;
+ }
+ }
+
+ binder::Status remoteRet;
+ hardware::camera2::utils::SubmitInfo info;
+ remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
+ int sequenceId = info.mRequestId;
+ int64_t lastFrameNumber = info.mLastFrameNumber;
+ if (sequenceId < 0) {
+ ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
+ mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+
+ if (isRepeating) {
+ // stopRepeating above should have cleanup repeating sequence id
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return ACAMERA_ERROR_CAMERA_DEVICE;
+ }
+ mRepeatingSequenceId = sequenceId;
+ } else {
+ mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+ }
+
+ if (mIdle) {
+ sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+ msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+ postSessionMsgAndCleanup(msg);
+ }
+ mIdle = false;
+ mBusySession = session;
+
+ if (captureSequenceId) {
+ *captureSequenceId = sequenceId;
+ }
+ return ACAMERA_OK;
+}
+
+} // namespace acam
+} // namespace android
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 94b5713..c661233 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -50,6 +50,7 @@
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS:
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE:
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT:
+ case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA:
return true;
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING:
case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING:
@@ -79,11 +80,41 @@
uint8_t capability = entry.data.u8[i];
if (isNdkSupportedCapability(capability)) {
capabilities.push(capability);
+
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+ derivePhysicalCameraIds();
+ }
}
}
mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
}
+void
+ACameraMetadata::derivePhysicalCameraIds() {
+ ACameraMetadata_const_entry entry;
+ auto ret = getConstEntry(ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS, &entry);
+ if (ret != ACAMERA_OK) {
+ ALOGE("%s: Get ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS key failed. ret %d",
+ __FUNCTION__, ret);
+ return;
+ }
+
+ const uint8_t* ids = entry.data.u8;
+ size_t start = 0;
+ for (size_t i = 0; i < entry.count; ++i) {
+ if (ids[i] == '\0') {
+ if (start != i) {
+ mStaticPhysicalCameraIds.push_back((const char*)ids+start);
+ }
+ start = i+1;
+ }
+ }
+
+ if (mStaticPhysicalCameraIds.size() < 2) {
+ ALOGW("%s: Logical multi-camera device only has %zu physical cameras",
+ __FUNCTION__, mStaticPhysicalCameraIds.size());
+ }
+}
void
ACameraMetadata::filterDurations(uint32_t tag) {
@@ -309,6 +340,27 @@
return mData;
}
+bool
+ACameraMetadata::isLogicalMultiCamera(size_t* count, const char*const** physicalCameraIds) const {
+ if (mType != ACM_CHARACTERISTICS) {
+ ALOGE("%s must be called for a static metadata!", __FUNCTION__);
+ return false;
+ }
+ if (count == nullptr || physicalCameraIds == nullptr) {
+ ALOGE("%s: Invalid input count: %p, physicalCameraIds: %p", __FUNCTION__,
+ count, physicalCameraIds);
+ return false;
+ }
+
+ if (mStaticPhysicalCameraIds.size() >= 2) {
+ *count = mStaticPhysicalCameraIds.size();
+ *physicalCameraIds = mStaticPhysicalCameraIds.data();
+ return true;
+ }
+
+ return false;
+}
+
// TODO: some of key below should be hidden from user
// ex: ACAMERA_REQUEST_ID and ACAMERA_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h
index f21dbaf..7049c4b 100644
--- a/camera/ndk/impl/ACameraMetadata.h
+++ b/camera/ndk/impl/ACameraMetadata.h
@@ -17,6 +17,7 @@
#define _ACAMERA_METADATA_H
#include <unordered_set>
+#include <vector>
#include <sys/types.h>
#include <utils/Mutex.h>
@@ -65,6 +66,7 @@
/*out*/const uint32_t** tags) const;
const CameraMetadata& getInternalData() const;
+ bool isLogicalMultiCamera(size_t* count, const char* const** physicalCameraIds) const;
private:
@@ -74,6 +76,7 @@
void filterUnsupportedFeatures(); // Hide features not yet supported by NDK
void filterStreamConfigurations(); // Hide input streams, translate hal format to NDK formats
void filterDurations(uint32_t tag); // translate hal format to NDK formats
+ void derivePhysicalCameraIds(); // Derive array of physical ids.
template<typename INTERNAL_T, typename NDK_T>
camera_status_t updateImpl(uint32_t tag, uint32_t count, const NDK_T* data) {
@@ -112,6 +115,8 @@
const ACAMERA_METADATA_TYPE mType;
static std::unordered_set<uint32_t> sSystemTags;
+
+ std::vector<const char*> mStaticPhysicalCameraIds;
};
#endif // _ACAMERA_METADATA_H
diff --git a/camera/ndk/include/camera/NdkCameraCaptureSession.h b/camera/ndk/include/camera/NdkCameraCaptureSession.h
index 1244582..d13a818 100644
--- a/camera/ndk/include/camera/NdkCameraCaptureSession.h
+++ b/camera/ndk/include/camera/NdkCameraCaptureSession.h
@@ -643,6 +643,103 @@
ACaptureSessionOutput* output) __INTRODUCED_IN(28);
#endif /* __ANDROID_API__ >= 28 */
+#if __ANDROID_API__ >= 29
+/**
+ * The definition of final capture result callback with logical multi-camera support.
+ *
+ * This has the same functionality as final ACameraCaptureSession_captureCallback_result, with
+ * added ability to return physical camera result metadata within a logical multi-camera.
+ *
+ * For a logical multi-camera, this function will be called with the Id and result metadata
+ * of the underlying physical cameras, which the corresponding capture request contains targets for.
+ * If the capture request doesn't contain targets specific to any physical camera, or the current
+ * camera device isn't a logical multi-camera, physicalResultCount will be 0.
+ *
+ * @param context The optional application context provided by user in
+ * {@link ACameraCaptureSession_captureCallbacks}.
+ * @param session The camera capture session of interest.
+ * @param request The capture request of interest. Note that this pointer points to a copy of
+ * capture request sent by application, so the address is different to what
+ * application sent but the content will match. This request will be freed by
+ * framework immediately after this callback returns.
+ * @param result The capture result metadata reported by camera device. The memory is managed by
+ * camera framework. Do not access this pointer after this callback returns.
+ * @param physicalResultCount The number of physical camera result metadata
+ * @param physicalCameraIds The array of physical camera IDs on which the
+ * physical result metadata are reported.
+ * @param physicalResults The array of capture result metadata reported by the
+ * physical camera devices.
+ */
+typedef void (*ACameraCaptureSession_logicalCamera_captureCallback_result)(
+ void* context, ACameraCaptureSession* session,
+ ACaptureRequest* request, const ACameraMetadata* result,
+ size_t physicalResultCount, const char** physicalCameraIds,
+ const ACameraMetadata** physicalResults);
+
+/**
+ * This has the same functionality as ACameraCaptureSession_captureCallbacks,
+ * with the exception that an onLogicalCameraCaptureCompleted callback is
+ * used, instead of onCaptureCompleted, to support logical multi-camera.
+ */
+typedef struct ACameraCaptureSession_logicalCamera_captureCallbacks {
+ /**
+ * Same as ACameraCaptureSession_captureCallbacks
+ */
+ void* context;
+ ACameraCaptureSession_captureCallback_start onCaptureStarted;
+ ACameraCaptureSession_captureCallback_result onCaptureProgressed;
+
+ /**
+ * This callback is called when an image capture has fully completed and all the
+ * result metadata is available. For a logical multi-camera, this callback
+ * also returns the result metadata for all physical cameras being
+ * explicitly requested on.
+ *
+ * <p>This callback will always fire after the last {@link onCaptureProgressed};
+ * in other words, no more partial results will be delivered once the completed result
+ * is available.</p>
+ *
+ * <p>For performance-intensive use-cases where latency is a factor, consider
+ * using {@link onCaptureProgressed} instead.</p>
+ *
+ * <p>Note that the ACaptureRequest pointer in the callback will not match what application has
+ * submitted, but the contents the ACaptureRequest will match what application submitted.</p>
+ */
+ ACameraCaptureSession_logicalCamera_captureCallback_result onLogicalCameraCaptureCompleted;
+
+ /**
+ * Same as ACameraCaptureSession_captureCallbacks
+ */
+ ACameraCaptureSession_captureCallback_failed onCaptureFailed;
+ ACameraCaptureSession_captureCallback_sequenceEnd onCaptureSequenceCompleted;
+ ACameraCaptureSession_captureCallback_sequenceAbort onCaptureSequenceAborted;
+ ACameraCaptureSession_captureCallback_bufferLost onCaptureBufferLost;
+} ACameraCaptureSession_logicalCamera_captureCallbacks;
+
+/**
+ * This has the same functionality as ACameraCaptureSession_capture, with added
+ * support for logical multi-camera where the capture callbacks supports result metadata for
+ * physical cameras.
+ */
+camera_status_t ACameraCaptureSession_logicalCamera_capture(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* callbacks,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) __INTRODUCED_IN(29);
+
+/**
+ * This has the same functionality as ACameraCaptureSession_setRepeatingRequest, with added
+ * support for logical multi-camera where the capture callbacks supports result metadata for
+ * physical cameras.
+ */
+camera_status_t ACameraCaptureSession_logicalCamera_setRepeatingRequest(
+ ACameraCaptureSession* session,
+ /*optional*/ACameraCaptureSession_logicalCamera_captureCallbacks* callbacks,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
__END_DECLS
#endif /* _NDK_CAMERA_CAPTURE_SESSION_H */
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index 4fe43d5..26af4f8 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -765,6 +765,36 @@
#endif /* __ANDROID_API__ >= 28 */
+#if __ANDROID_API__ >= 29
+
+/**
+ * Create a ACaptureSessionOutput object used for streaming from a physical
+ * camera as part of a logical camera device.
+ *
+ * <p>The ACaptureSessionOutput is used in {@link ACaptureSessionOutputContainer_add} method to add
+ * an output {@link ANativeWindow} to ACaptureSessionOutputContainer. Use
+ * {@link ACaptureSessionOutput_free} to free the object and its memory after application no longer
+ * needs the {@link ACaptureSessionOutput}.</p>
+ *
+ * @param anw the {@link ANativeWindow} to be associated with the {@link ACaptureSessionOutput}
+ * @param physicalId the Id of the physical camera this output is associated
+ * with.
+ * @param output the output {@link ACaptureSessionOutput} will be stored here if the
+ * method call succeeds.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds. The created container will be
+ * filled in the output argument.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if anw, physicalId or output is NULL.</li></ul>
+ *
+ * @see ACaptureSessionOutputContainer_add
+ */
+camera_status_t ACaptureSessionPhysicalOutput_create(
+ ACameraWindowType* anw, const char* physicalId,
+ /*out*/ACaptureSessionOutput** output) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
__END_DECLS
#endif /* _NDK_CAMERA_DEVICE_H */
diff --git a/camera/ndk/include/camera/NdkCameraMetadata.h b/camera/ndk/include/camera/NdkCameraMetadata.h
index 611e270..9bbfb83 100644
--- a/camera/ndk/include/camera/NdkCameraMetadata.h
+++ b/camera/ndk/include/camera/NdkCameraMetadata.h
@@ -233,6 +233,28 @@
#endif /* __ANDROID_API__ >= 24 */
+#if __ANDROID_API__ >= 29
+
+/**
+ * Helper function to check if a camera is logical multi-camera.
+ *
+ * <p> Check whether a camera device is a logical multi-camera based on its
+ * static metadata. If it is, also returns its physical sub camera Ids.</p>
+ *
+ * @param staticMetadata the static metadata of the camera being checked.
+ * @param numPhysicalCameras returns the number of physical cameras.
+ * @param physicalCameraIds returns the array of physical camera Ids backing this logical
+ * camera device. Note that this pointer is only valid
+ * during the lifetime of the staticMetadata object.
+ *
+ * @return true if this is a logical multi-camera, false otherwise.
+ */
+bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,
+ /*out*/size_t* numPhysicalCameras, /*out*/const char* const** physicalCameraIds)
+ __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
+
__END_DECLS
#endif /* _NDK_CAMERA_METADATA_H */
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index cb474f4..4bb74cb 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -5552,6 +5552,25 @@
ACAMERA_DEPTH_END,
/**
+ * <p>String containing the ids of the underlying physical cameras.</p>
+ *
+ * <p>Type: byte[n]</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>For a logical camera, this is concatenation of all underlying physical camera ids.
+ * The null terminator for physical camera id must be preserved so that the whole string
+ * can be tokenized using '\0' to generate list of physical camera ids.</p>
+ * <p>For example, if the physical camera ids of the logical camera are "2" and "3", the
+ * value of this tag will be ['2', '\0', '3', '\0'].</p>
+ * <p>The number of physical camera ids must be no less than 2.</p>
+ */
+ ACAMERA_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS = // byte[n]
+ ACAMERA_LOGICAL_MULTI_CAMERA_START,
+ /**
* <p>The accuracy of frame timestamp synchronization between physical cameras</p>
*
* <p>Type: byte (acamera_metadata_enum_android_logical_multi_camera_sensor_sync_type_t)</p>
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index a29e96d..5a00022 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -2,9 +2,11 @@
global:
ACameraCaptureSession_abortCaptures;
ACameraCaptureSession_capture;
+ ACameraCaptureSession_logicalCamera_capture; # introduced=29
ACameraCaptureSession_close;
ACameraCaptureSession_getDevice;
ACameraCaptureSession_setRepeatingRequest;
+ ACameraCaptureSession_logicalCamera_setRepeatingRequest; # introduced=29
ACameraCaptureSession_stopRepeating;
ACameraCaptureSession_updateSharedOutput; # introduced=28
ACameraDevice_close;
@@ -24,6 +26,7 @@
ACameraMetadata_free;
ACameraMetadata_getAllTags;
ACameraMetadata_getConstEntry;
+ ACameraMetadata_isLogicalMultiCamera; # introduced=29
ACameraOutputTarget_create;
ACameraOutputTarget_free;
ACaptureRequest_addTarget;
@@ -48,6 +51,7 @@
ACaptureSessionSharedOutput_create; # introduced=28
ACaptureSessionSharedOutput_add; # introduced=28
ACaptureSessionSharedOutput_remove; # introduced=28
+ ACaptureSessionPhysicalOutput_create; # introduced=29
ACaptureSessionOutput_free;
local:
*;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
index 8d9e90c..e1af8c1 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
@@ -14,11 +14,13 @@
* limitations under the License.
*/
+#include <string>
#include "utils.h"
struct ACaptureSessionOutput {
- explicit ACaptureSessionOutput(native_handle_t* window, bool isShared = false) :
- mWindow(window), mIsShared(isShared) {};
+ explicit ACaptureSessionOutput(native_handle_t* window, bool isShared = false,
+ const char* physicalCameraId = "") :
+ mWindow(window), mIsShared(isShared), mPhysicalCameraId(physicalCameraId) {};
bool operator == (const ACaptureSessionOutput& other) const {
return (mWindow == other.mWindow);
@@ -40,6 +42,7 @@
std::set<android::acam::utils::native_handle_ptr_wrapper> mSharedWindows;
bool mIsShared;
int mRotation = CAMERA3_STREAM_ROTATION_0;
+ std::string mPhysicalCameraId;
};
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 26e6b3c..f7863a5 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -29,6 +29,8 @@
#include "ACaptureRequest.h"
#include "utils.h"
+#include "ACameraCaptureSession.inc"
+
using namespace android;
namespace android {
@@ -47,6 +49,7 @@
const char* CameraDevice::kCaptureRequestKey = "CaptureRequest";
const char* CameraDevice::kTimeStampKey = "TimeStamp";
const char* CameraDevice::kCaptureResultKey = "CaptureResult";
+const char* CameraDevice::kPhysicalCaptureResultKey = "PhysicalCaptureResult";
const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
const char* CameraDevice::kSequenceIdKey = "SequenceId";
const char* CameraDevice::kFrameNumberKey = "FrameNumber";
@@ -206,28 +209,8 @@
return ACAMERA_OK;
}
-camera_status_t
-CameraDevice::captureLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- return submitRequestsLocked(
- session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
-}
-
-camera_status_t
-CameraDevice::setRepeatingRequestsLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId) {
- return submitRequestsLocked(
- session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
-}
-
-void addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest,
- sp<CaptureRequest> &req) {
+void CameraDevice::addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest,
+ sp<CaptureRequest> &req) {
CameraMetadata metadataCopy = aCaptureRequest->settings->getInternalData();
const camera_metadata_t *camera_metadata = metadataCopy.getAndLock();
HCameraMetadata hCameraMetadata;
@@ -237,101 +220,6 @@
req->mPhysicalCameraSettings[0].settings.metadata(std::move(hCameraMetadata));
}
-camera_status_t
-CameraDevice::submitRequestsLocked(
- sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
- int numRequests, ACaptureRequest** requests,
- /*optional*/int* captureSequenceId,
- bool isRepeating) {
- camera_status_t ret = checkCameraClosedOrErrorLocked();
- if (ret != ACAMERA_OK) {
- ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
- return ret;
- }
-
- // Form two vectors of capture request, one for internal tracking
- std::vector<frameworks::cameraservice::device::V2_0::CaptureRequest> requestList;
- Vector<sp<CaptureRequest>> requestsV;
- requestsV.setCapacity(numRequests);
- for (int i = 0; i < numRequests; i++) {
- sp<CaptureRequest> req;
- ret = allocateCaptureRequest(requests[i], req);
- // We need to call this method since after submitRequestList is called,
- // the request metadata queue might have removed the capture request
- // metadata. Therefore we simply add the metadata to its wrapper class,
- // so that it can be retrived later.
- addRequestSettingsMetadata(requests[i], req);
- if (ret != ACAMERA_OK) {
- ALOGE("Convert capture request to internal format failure! ret %d", ret);
- return ret;
- }
- if (req->mCaptureRequest.streamAndWindowIds.size() == 0) {
- ALOGE("Capture request without output target cannot be submitted!");
- return ACAMERA_ERROR_INVALID_PARAMETER;
- }
- requestList.push_back(utils::convertToHidl(req.get()));
- requestsV.push_back(req);
- }
- if (isRepeating) {
- ret = stopRepeatingLocked();
- if (ret != ACAMERA_OK) {
- ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
- return ret;
- }
- }
-
- SubmitInfo info;
- Status status;
- auto remoteRet = mRemote->submitRequestList(requestList, isRepeating,
- [&status, &info](auto s, auto &submitInfo) {
- status = s;
- info = submitInfo;
- });
- if (!remoteRet.isOk()) {
- ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__,
- remoteRet.description().c_str());
- }
- if (status != Status::NO_ERROR) {
- return utils::convertFromHidl(status);
- }
- int32_t sequenceId = info.requestId;
- int64_t lastFrameNumber = info.lastFrameNumber;
- if (sequenceId < 0) {
- ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
- return ACAMERA_ERROR_UNKNOWN;
- }
-
- CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
- mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
-
- if (isRepeating) {
- // stopRepeating above should have cleanup repeating sequence id
- if (mRepeatingSequenceId != REQUEST_ID_NONE) {
- setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
- return ACAMERA_ERROR_CAMERA_DEVICE;
- }
- mRepeatingSequenceId = sequenceId;
- } else {
- mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
- }
-
- if (mIdle) {
- sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
- msg->setPointer(kContextKey, session->mUserSessionCallback.context);
- msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
- postSessionMsgAndCleanup(msg);
- }
- mIdle = false;
- mBusySession = session;
-
- if (captureSequenceId) {
- *captureSequenceId = sequenceId;
- }
- return ACAMERA_OK;
-}
-
camera_status_t CameraDevice::updateOutputConfigurationLocked(ACaptureSessionOutput *output) {
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
@@ -365,6 +253,7 @@
outConfig.windowGroupId = -1; // ndk doesn't support inter OutputConfiguration buffer sharing.
outConfig.windowHandles.resize(output->mSharedWindows.size() + 1);
outConfig.windowHandles[0] = output->mWindow;
+ outConfig.physicalCameraId = output->mPhysicalCameraId;
int i = 1;
for (auto& anw : output->mSharedWindows) {
outConfig.windowHandles[i++] = anw;
@@ -668,6 +557,7 @@
outConfigInsert.windowGroupId = -1;
outConfigInsert.windowHandles.resize(outConfig.mSharedWindows.size() + 1);
outConfigInsert.windowHandles[0] = anw;
+ outConfigInsert.physicalCameraId = outConfig.mPhysicalCameraId;
native_handle_ptr_wrapper wrap(anw);
outputSet.insert(std::make_pair(anw, outConfigInsertW));
}
@@ -894,7 +784,7 @@
if (errorCode == ErrorCode::CAMERA_BUFFER) {
int32_t streamId = resultExtras.errorStreamId;
ACameraCaptureSession_captureCallback_bufferLost onBufferLost =
- cbh.mCallbacks.onCaptureBufferLost;
+ cbh.mOnCaptureBufferLost;
auto outputPairIt = mConfiguredOutputs.find(streamId);
if (outputPairIt == mConfiguredOutputs.end()) {
ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId);
@@ -913,7 +803,7 @@
getId(), anw, frameNumber);
sp<AMessage> msg = new AMessage(kWhatCaptureBufferLost, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onBufferLost);
msg->setObject(kCaptureRequestKey, request);
@@ -925,7 +815,7 @@
}
} else { // Handle other capture failures
// Fire capture failure callback if there is one registered
- ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
+ ACameraCaptureSession_captureCallback_failed onError = cbh.mOnCaptureFailed;
sp<CameraCaptureFailure> failure(new CameraCaptureFailure());
failure->frameNumber = frameNumber;
// TODO: refine this when implementing flush
@@ -934,7 +824,7 @@
failure->wasImageCaptured = (errorCode == ErrorCode::CAMERA_RESULT);
sp<AMessage> msg = new AMessage(kWhatCaptureFail, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onError);
msg->setObject(kCaptureRequestKey, request);
@@ -956,6 +846,7 @@
case kWhatSessionStateCb:
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
@@ -1026,6 +917,7 @@
case kWhatSessionStateCb:
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
@@ -1043,6 +935,7 @@
switch (msg->what()) {
case kWhatCaptureStart:
case kWhatCaptureResult:
+ case kWhatLogicalCaptureResult:
case kWhatCaptureFail:
case kWhatCaptureBufferLost:
found = msg->findObject(kCaptureRequestKey, &obj);
@@ -1114,6 +1007,62 @@
freeACaptureRequest(request);
break;
}
+ case kWhatLogicalCaptureResult:
+ {
+ ACameraCaptureSession_logicalCamera_captureCallback_result onResult;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onResult);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result callback!", __FUNCTION__);
+ return;
+ }
+ if (onResult == nullptr) {
+ return;
+ }
+
+ found = msg->findObject(kCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find capture result!", __FUNCTION__);
+ return;
+ }
+ sp<ACameraMetadata> result(static_cast<ACameraMetadata*>(obj.get()));
+
+ found = msg->findObject(kPhysicalCaptureResultKey, &obj);
+ if (!found) {
+ ALOGE("%s: Cannot find physical capture result!", __FUNCTION__);
+ return;
+ }
+ sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+ static_cast<ACameraPhysicalCaptureResultInfo*>(obj.get()));
+ std::vector<PhysicalCaptureResultInfoLocal>& physicalResultInfo =
+ physicalResult->mPhysicalResultInfo;
+
+ std::vector<std::string> physicalCameraIds;
+ std::vector<sp<ACameraMetadata>> physicalMetadataCopy;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ physicalCameraIds.push_back(physicalResultInfo[i].physicalCameraId);
+
+ CameraMetadata clone = physicalResultInfo[i].physicalMetadata;
+ clone.update(ANDROID_SYNC_FRAME_NUMBER,
+ &physicalResult->mFrameNumber, /*data_count*/1);
+ sp<ACameraMetadata> metadata =
+ new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT);
+ physicalMetadataCopy.push_back(metadata);
+ }
+ std::vector<const char*> physicalCameraIdPtrs;
+ std::vector<const ACameraMetadata*> physicalMetadataCopyPtrs;
+ for (size_t i = 0; i < physicalResultInfo.size(); i++) {
+ physicalCameraIdPtrs.push_back(physicalCameraIds[i].c_str());
+ physicalMetadataCopyPtrs.push_back(physicalMetadataCopy[i].get());
+ }
+
+ ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ (*onResult)(context, session.get(), request, result.get(),
+ physicalResultInfo.size(), physicalCameraIdPtrs.data(),
+ physicalMetadataCopyPtrs.data());
+ freeACaptureRequest(request);
+ break;
+ }
+
case kWhatCaptureFail:
{
ACameraCaptureSession_captureCallback_failed onFail;
@@ -1224,12 +1173,34 @@
}
CameraDevice::CallbackHolder::CallbackHolder(
- sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest> >& requests,
- bool isRepeating,
- ACameraCaptureSession_captureCallbacks* cbs) :
- mSession(session), mRequests(requests),
- mIsRepeating(isRepeating), mCallbacks(fillCb(cbs)) {}
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_captureCallbacks* cbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(false) {
+ initCaptureCallbacks(cbs);
+
+ if (cbs != nullptr) {
+ mOnCaptureCompleted = cbs->onCaptureCompleted;
+ }
+}
+
+CameraDevice::CallbackHolder::CallbackHolder(
+ sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest> >& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
+ mSession(session), mRequests(requests),
+ mIsRepeating(isRepeating),
+ mIsLogicalCameraCallback(true) {
+ initCaptureCallbacks(lcbs);
+
+ if (lcbs != nullptr) {
+ mOnLogicalCameraCaptureCompleted = lcbs->onLogicalCameraCaptureCompleted;
+ }
+}
void
CameraDevice::checkRepeatingSequenceCompleteLocked(
@@ -1246,9 +1217,9 @@
mSequenceCallbackMap.erase(cbIt);
// send seq aborted callback
sp<AMessage> msg = new AMessage(kWhatCaptureSeqAbort, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceAborted);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceAborted);
msg->setInt32(kSequenceIdKey, sequenceId);
postSessionMsgAndCleanup(msg);
} else {
@@ -1295,9 +1266,9 @@
mSequenceCallbackMap.erase(cbIt);
// send seq complete callback
sp<AMessage> msg = new AMessage(kWhatCaptureSeqEnd, mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, cbh.mSession);
- msg->setPointer(kCallbackFpKey, (void*) cbh.mCallbacks.onCaptureSequenceCompleted);
+ msg->setPointer(kCallbackFpKey, (void*) cbh.mOnCaptureSequenceCompleted);
msg->setInt32(kSequenceIdKey, sequenceId);
msg->setInt64(kFrameNumberKey, lastFrameNumber);
@@ -1454,7 +1425,7 @@
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_start onStart = cbh.mCallbacks.onCaptureStarted;
+ ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1463,7 +1434,7 @@
}
sp<CaptureRequest> request = cbh.mRequests[burstId];
sp<AMessage> msg = new AMessage(kWhatCaptureStart, dev->mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
msg->setPointer(kCallbackFpKey, (void*) onStart);
msg->setObject(kCaptureRequestKey, request);
@@ -1478,7 +1449,6 @@
const FmqSizeOrMetadata& resultMetadata,
const CaptureResultExtras& resultExtras,
const hidl_vec<PhysicalCaptureResultInfo>& physicalResultInfos) {
- (void) physicalResultInfos;
auto ret = Void();
sp<CameraDevice> dev = mDevice.promote();
@@ -1508,27 +1478,10 @@
}
CameraMetadata metadataCopy;
- HCameraMetadata hCameraMetadata;
- bool converted = false;
- if (resultMetadata.getDiscriminator() ==
- FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
- hCameraMetadata.resize(resultMetadata.fmqMetadataSize());
- bool read = dev->mCaptureResultMetadataQueue->read(hCameraMetadata.data(),
- resultMetadata.fmqMetadataSize());
- if (!read) {
- ALOGE("%s capture request settings could't be read from fmq",
- __FUNCTION__);
- return ret;
- }
- // TODO: Do we actually need to clone here ?
- converted = utils::convertFromHidlCloned(hCameraMetadata, &metadataCopy);
-
- } else {
- converted = utils::convertFromHidlCloned(resultMetadata.metadata(), &metadataCopy);
- }
-
- if (!converted) {
- ALOGE("%s result metadata couldn't be converted", __FUNCTION__);
+ camera_status_t status = readOneResultMetadata(resultMetadata,
+ dev->mCaptureResultMetadataQueue.get(), &metadataCopy);
+ if (status != ACAMERA_OK) {
+ ALOGE("%s: result metadata couldn't be converted", __FUNCTION__);
return ret;
}
@@ -1538,9 +1491,6 @@
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_result onResult = isPartialResult ?
- cbh.mCallbacks.onCaptureProgressed :
- cbh.mCallbacks.onCaptureCompleted;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -1551,12 +1501,39 @@
sp<ACameraMetadata> result(new ACameraMetadata(
metadataCopy.release(), ACameraMetadata::ACM_RESULT));
- sp<AMessage> msg = new AMessage(kWhatCaptureResult, dev->mHandler);
- msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ std::vector<PhysicalCaptureResultInfoLocal> localPhysicalResult;
+ localPhysicalResult.resize(physicalResultInfos.size());
+ for (size_t i = 0; i < physicalResultInfos.size(); i++) {
+ localPhysicalResult[i].physicalCameraId = physicalResultInfos[i].physicalCameraId;
+ status = readOneResultMetadata(physicalResultInfos[i].physicalCameraMetadata,
+ dev->mCaptureResultMetadataQueue.get(),
+ &localPhysicalResult[i].physicalMetadata);
+ if (status != ACAMERA_OK) {
+ ALOGE("%s: physical camera result metadata couldn't be converted", __FUNCTION__);
+ return ret;
+ }
+ }
+ sp<ACameraPhysicalCaptureResultInfo> physicalResult(
+ new ACameraPhysicalCaptureResultInfo(localPhysicalResult, frameNumber));
+
+ sp<AMessage> msg = new AMessage(
+ cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureResult : kWhatCaptureResult,
+ dev->mHandler);
+ msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
- msg->setPointer(kCallbackFpKey, (void*) onResult);
msg->setObject(kCaptureRequestKey, request);
msg->setObject(kCaptureResultKey, result);
+ if (isPartialResult) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureProgressed);
+ } else if (cbh.mIsLogicalCameraCallback) {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnLogicalCameraCaptureCompleted);
+ msg->setObject(kPhysicalCaptureResultKey, physicalResult);
+ } else {
+ msg->setPointer(kCallbackFpKey,
+ (void *)cbh.mOnCaptureCompleted);
+ }
dev->postSessionMsgAndCleanup(msg);
}
@@ -1590,5 +1567,31 @@
return ret;
}
+camera_status_t CameraDevice::ServiceCallback::readOneResultMetadata(
+ const FmqSizeOrMetadata& fmqSizeOrMetadata, ResultMetadataQueue* metadataQueue,
+ CameraMetadata* metadata) {
+ if (metadataQueue == nullptr || metadata == nullptr) {
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ bool converted;
+ HCameraMetadata hCameraMetadata;
+ if (fmqSizeOrMetadata.getDiscriminator() ==
+ FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
+ hCameraMetadata.resize(fmqSizeOrMetadata.fmqMetadataSize());
+ bool read = metadataQueue->read(
+ hCameraMetadata.data(), fmqSizeOrMetadata.fmqMetadataSize());
+ if (!read) {
+ ALOGE("%s capture request settings could't be read from fmq", __FUNCTION__);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ // TODO: Do we actually need to clone here ?
+ converted = utils::convertFromHidlCloned(hCameraMetadata, metadata);
+ } else {
+ converted = utils::convertFromHidlCloned(fmqSizeOrMetadata.metadata(), metadata);
+ }
+
+ return converted ? ACAMERA_OK : ACAMERA_ERROR_UNKNOWN;
+}
+
} // namespace acam
} // namespace android
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index 01a219f..c63b97f 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -21,6 +21,7 @@
#include <set>
#include <atomic>
#include <utility>
+#include <vector>
#include <utils/StrongPointer.h>
#include <utils/Mutex.h>
#include <utils/List.h>
@@ -65,6 +66,21 @@
// Wrap ACameraCaptureFailure so it can be ref-counted
struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure { };
+// Wrap PhysicalCaptureResultInfo so that it can be ref-counted
+struct PhysicalCaptureResultInfoLocal {
+ std::string physicalCameraId;
+ CameraMetadata physicalMetadata;
+};
+
+struct ACameraPhysicalCaptureResultInfo: public RefBase {
+ ACameraPhysicalCaptureResultInfo(const std::vector<PhysicalCaptureResultInfoLocal>& info,
+ int64_t frameNumber) :
+ mPhysicalResultInfo(info), mFrameNumber(frameNumber) {}
+
+ std::vector<PhysicalCaptureResultInfoLocal> mPhysicalResultInfo;
+ int64_t mFrameNumber;
+};
+
class CameraDevice final : public RefBase {
public:
CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
@@ -99,6 +115,8 @@
android::hardware::Return<void> onRepeatingRequestError(uint64_t lastFrameNumber,
int32_t stoppedSequenceId) override;
private:
+ camera_status_t readOneResultMetadata(const FmqSizeOrMetadata& fmqSizeOrMetadata,
+ ResultMetadataQueue* metadataQueue, CameraMetadata* metadata);
const wp<CameraDevice> mDevice;
};
inline sp<ICameraDeviceCallback> getServiceCallback() {
@@ -127,24 +145,28 @@
camera_status_t waitUntilIdleLocked();
-
+ template<class T>
camera_status_t captureLocked(sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template<class T>
camera_status_t setRepeatingRequestsLocked(sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId);
+ template<class T>
camera_status_t submitRequestsLocked(
sp<ACameraCaptureSession> session,
- /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
+ /*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*out*/int* captureSequenceId,
bool isRepeating);
+ void addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest, sp<CaptureRequest> &req);
+
camera_status_t updateOutputConfigurationLocked(ACaptureSessionOutput *output);
camera_status_t allocateCaptureRequest(
@@ -206,6 +228,7 @@
// Capture callbacks
kWhatCaptureStart, // onCaptureStarted
kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
+ kWhatLogicalCaptureResult, // onLogicalCameraCaptureCompleted
kWhatCaptureFail, // onCaptureFailed
kWhatCaptureSeqEnd, // onCaptureSequenceCompleted
kWhatCaptureSeqAbort, // onCaptureSequenceAborted
@@ -221,6 +244,7 @@
static const char* kCaptureRequestKey;
static const char* kTimeStampKey;
static const char* kCaptureResultKey;
+ static const char* kPhysicalCaptureResultKey;
static const char* kCaptureFailureKey;
static const char* kSequenceIdKey;
static const char* kFrameNumberKey;
@@ -259,19 +283,47 @@
const Vector<sp<CaptureRequest>>& requests,
bool isRepeating,
ACameraCaptureSession_captureCallbacks* cbs);
+ CallbackHolder(sp<ACameraCaptureSession> session,
+ const Vector<sp<CaptureRequest>>& requests,
+ bool isRepeating,
+ ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
- static ACameraCaptureSession_captureCallbacks fillCb(
- ACameraCaptureSession_captureCallbacks* cbs) {
+ template <class T>
+ void initCaptureCallbacks(T* cbs) {
+ mContext = nullptr;
+ mOnCaptureStarted = nullptr;
+ mOnCaptureProgressed = nullptr;
+ mOnCaptureCompleted = nullptr;
+ mOnLogicalCameraCaptureCompleted = nullptr;
+ mOnCaptureFailed = nullptr;
+ mOnCaptureSequenceCompleted = nullptr;
+ mOnCaptureSequenceAborted = nullptr;
+ mOnCaptureBufferLost = nullptr;
if (cbs != nullptr) {
- return *cbs;
+ mContext = cbs->context;
+ mOnCaptureStarted = cbs->onCaptureStarted;
+ mOnCaptureProgressed = cbs->onCaptureProgressed;
+ mOnCaptureFailed = cbs->onCaptureFailed;
+ mOnCaptureSequenceCompleted = cbs->onCaptureSequenceCompleted;
+ mOnCaptureSequenceAborted = cbs->onCaptureSequenceAborted;
+ mOnCaptureBufferLost = cbs->onCaptureBufferLost;
}
- return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
}
sp<ACameraCaptureSession> mSession;
- Vector<sp<CaptureRequest>> mRequests;
+ Vector<sp<CaptureRequest>> mRequests;
const bool mIsRepeating;
- ACameraCaptureSession_captureCallbacks mCallbacks;
+ const bool mIsLogicalCameraCallback;
+
+ void* mContext;
+ ACameraCaptureSession_captureCallback_start mOnCaptureStarted;
+ ACameraCaptureSession_captureCallback_result mOnCaptureProgressed;
+ ACameraCaptureSession_captureCallback_result mOnCaptureCompleted;
+ ACameraCaptureSession_logicalCamera_captureCallback_result mOnLogicalCameraCaptureCompleted;
+ ACameraCaptureSession_captureCallback_failed mOnCaptureFailed;
+ ACameraCaptureSession_captureCallback_sequenceEnd mOnCaptureSequenceCompleted;
+ ACameraCaptureSession_captureCallback_sequenceAbort mOnCaptureSequenceAborted;
+ ACameraCaptureSession_captureCallback_bufferLost mOnCaptureBufferLost;
};
// sequence id -> callbacks map
std::map<int, CallbackHolder> mSequenceCallbackMap;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
new file mode 100644
index 0000000..7d2304e
--- /dev/null
+++ b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vector>
+#include <inttypes.h>
+#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
+#include <android/frameworks/cameraservice/device/2.0/types.h>
+#include <CameraMetadata.h>
+
+#include "ndk_vendor/impl/ACameraDevice.h"
+#include "ACameraCaptureSession.h"
+#include "ACameraMetadata.h"
+#include "ACaptureRequest.h"
+#include "utils.h"
+
+using namespace android;
+
+namespace android {
+namespace acam {
+
+template<class T>
+camera_status_t
+CameraDevice::captureLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
+}
+
+template<class T>
+camera_status_t
+CameraDevice::setRepeatingRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*optional*/int* captureSequenceId) {
+ return submitRequestsLocked(
+ session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
+}
+
+template<class T>
+camera_status_t CameraDevice::submitRequestsLocked(
+ sp<ACameraCaptureSession> session,
+ /*optional*/T* cbs,
+ int numRequests, ACaptureRequest** requests,
+ /*out*/int* captureSequenceId,
+ bool isRepeating)
+{
+ camera_status_t ret = checkCameraClosedOrErrorLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
+ return ret;
+ }
+
+ // Form two vectors of capture request, one for internal tracking
+ std::vector<frameworks::cameraservice::device::V2_0::CaptureRequest> requestList;
+ Vector<sp<CaptureRequest>> requestsV;
+ requestsV.setCapacity(numRequests);
+ for (int i = 0; i < numRequests; i++) {
+ sp<CaptureRequest> req;
+ ret = allocateCaptureRequest(requests[i], req);
+ // We need to call this method since after submitRequestList is called,
+ // the request metadata queue might have removed the capture request
+ // metadata. Therefore we simply add the metadata to its wrapper class,
+ // so that it can be retrieved later.
+ addRequestSettingsMetadata(requests[i], req);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Convert capture request to internal format failure! ret %d", ret);
+ return ret;
+ }
+ if (req->mCaptureRequest.streamAndWindowIds.size() == 0) {
+ ALOGE("Capture request without output target cannot be submitted!");
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ requestList.push_back(utils::convertToHidl(req.get()));
+ requestsV.push_back(req);
+ }
+ if (isRepeating) {
+ ret = stopRepeatingLocked();
+ if (ret != ACAMERA_OK) {
+ ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
+ return ret;
+ }
+ }
+
+ SubmitInfo info;
+ Status status;
+ auto remoteRet = mRemote->submitRequestList(requestList, isRepeating,
+ [&status, &info](auto s, auto &submitInfo) {
+ status = s;
+ info = submitInfo;
+ });
+ if (!remoteRet.isOk()) {
+ ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__,
+ remoteRet.description().c_str());
+ }
+ if (status != Status::NO_ERROR) {
+ return utils::convertFromHidl(status);
+ }
+ int32_t sequenceId = info.requestId;
+ int64_t lastFrameNumber = info.lastFrameNumber;
+ if (sequenceId < 0) {
+ ALOGE("Camera %s submit request remote failure: ret %d", getId(), sequenceId);
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+
+ CallbackHolder cbHolder(session, requestsV, isRepeating, cbs);
+ mSequenceCallbackMap.insert(std::make_pair(sequenceId, cbHolder));
+ if (isRepeating) {
+ // stopRepeating above should have cleanup repeating sequence id
+ if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
+ return ACAMERA_ERROR_CAMERA_DEVICE;
+ }
+ mRepeatingSequenceId = sequenceId;
+ } else {
+ mSequenceLastFrameNumberMap.insert(std::make_pair(sequenceId, lastFrameNumber));
+ }
+
+ if (mIdle) {
+ sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+ msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+ postSessionMsgAndCleanup(msg);
+ }
+ mIdle = false;
+ mBusySession = session;
+
+ if (captureSequenceId) {
+ *captureSequenceId = sequenceId;
+ }
+ return ACAMERA_OK;
+}
+
+} // namespace acam
+} // namespace android
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index fa8a7a3..8534b28 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -480,7 +480,8 @@
sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
- OutputConfiguration output(gbProducer, /*rotation*/0);
+ String16 noPhysicalId;
+ OutputConfiguration output(gbProducer, /*rotation*/0, noPhysicalId);
// Can we configure?
res = device->beginConfigure();