Implement session param injection in CameraService
- This allows injecting session params into existing camera clients.
- The injection is cleared upon the camera closing, and we do not keep
state from one camera open to the next.
- We restrict the injection to only allow overriding vendor tags for now.
- The actionable parts of the change are gated behind the inject_session_params
flag to allow easy flipping. When false, this feature will have no effect.
Bug: 308984721
Test: I tested that this works using adb shell.
Change-Id: I27d955d035dde57b63a220c5d68b505ec636c401
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index feb9c75..6acf0b6 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1092,6 +1092,39 @@
}
}
+Status CameraService::injectSessionParams(
+ const std::string& cameraId,
+ const CameraMetadata& sessionParams) {
+ if (!checkCallingPermission(toString16(sCameraInjectExternalCameraPermission))) {
+ const int pid = CameraThreadState::getCallingPid();
+ const int uid = CameraThreadState::getCallingUid();
+ ALOGE("%s: Permission Denial: can't inject session params pid=%d, uid=%d",
+ __FUNCTION__, pid, uid);
+ return STATUS_ERROR(ERROR_PERMISSION_DENIED,
+ "Permission Denial: no permission to inject session params");
+ }
+
+ std::unique_ptr<AutoConditionLock> serviceLockWrapper =
+ AutoConditionLock::waitAndAcquire(mServiceLockWrapper);
+
+ auto clientDescriptor = mActiveClientManager.get(cameraId);
+ if (clientDescriptor == nullptr) {
+ ALOGI("%s: No active client for camera id %s", __FUNCTION__, cameraId.c_str());
+ return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
+ "No active client for camera id %s", cameraId.c_str());
+ }
+
+ sp<BasicClient> clientSp = clientDescriptor->getValue();
+ status_t res = clientSp->injectSessionParams(sessionParams);
+
+ if (res != OK) {
+ return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
+ "Error injecting session params into camera \"%s\": %s (%d)",
+ cameraId.c_str(), strerror(-res), res);
+ }
+ return Status::ok();
+}
+
std::vector<std::string> CameraService::findOriginalIdsForRemappedCameraId(
const std::string& inputCameraId, int clientUid) {
std::string packageName = getPackageNameFromUid(clientUid);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index cabac17..7dc0b91 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -232,7 +232,11 @@
const hardware::CameraExtensionSessionStats& stats, std::string* sessionKey /*out*/);
virtual binder::Status remapCameraIds(const hardware::CameraIdRemapping&
- cameraIdRemapping);
+ cameraIdRemapping);
+
+ virtual binder::Status injectSessionParams(
+ const std::string& cameraId,
+ const hardware::camera2::impl::CameraMetadataNative& sessionParams);
virtual binder::Status createDefaultRequest(const std::string& cameraId, int templateId,
/*out*/
@@ -412,6 +416,10 @@
// Stop the injection camera and restore to internal camera session.
virtual status_t stopInjection() = 0;
+ // Inject session parameters into an existing session.
+ virtual status_t injectSessionParams(
+ const hardware::camera2::impl::CameraMetadataNative& sessionParams) = 0;
+
protected:
BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 4ed352d..dc9e0c1 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -383,5 +383,12 @@
return OK;
}
+status_t CameraOfflineSessionClient::injectSessionParams(
+ const hardware::camera2::impl::CameraMetadataNative& sessionParams) {
+ ALOGV("%s: This client doesn't support the injecting session parameters camera.",
+ __FUNCTION__);
+ (void)sessionParams;
+ return OK;
+}
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index 8aad4e9..804498f 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -120,6 +120,8 @@
status_t injectCamera(const std::string& injectedCamId,
sp<CameraProviderManager> manager) override;
status_t stopInjection() override;
+ status_t injectSessionParams(
+ const hardware::camera2::impl::CameraMetadataNative& sessionParams) override;
private:
mutable Mutex mBinderSerializationLock;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index c730b14..a126f61 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -509,6 +509,12 @@
return mDevice->stopInjection();
}
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::injectSessionParams(
+ const CameraMetadata& sessionParams) {
+ return mDevice->injectSessionParams(sessionParams);
+}
+
template class Camera2ClientBase<CameraService::Client>;
template class Camera2ClientBase<CameraDeviceClientBase>;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index bac4af8..2bb90d9 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -18,6 +18,7 @@
#define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H
#include "common/CameraDeviceBase.h"
+#include "camera/CameraMetadata.h"
#include "camera/CaptureResult.h"
#include "utils/CameraServiceProxyWrapper.h"
#include "CameraServiceWatchdog.h"
@@ -136,6 +137,8 @@
sp<CameraProviderManager> manager) override;
status_t stopInjection() override;
+ status_t injectSessionParams(const CameraMetadata& sessionParams) override;
+
protected:
// The PID provided in the constructor call
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 983b2c1..cfc41c3 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -509,6 +509,10 @@
*/
virtual status_t stopInjection() = 0;
+ // Inject session parameters into an existing client.
+ virtual status_t injectSessionParams(
+ const CameraMetadata& sessionParams) = 0;
+
protected:
bool mImageDumpMask = 0;
std::vector<int64_t> mStreamUseCaseOverrides;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 0a5b0c4..107cc19 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -80,7 +80,7 @@
namespace flags = com::android::internal::camera::flags;
namespace android {
-
+namespace flags = com::android::internal::camera::flags;
Camera3Device::Camera3Device(std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
const std::string &id, bool overrideForPerfClass, bool overrideToPortrait,
bool legacyClient):
@@ -3596,6 +3596,9 @@
captureRequest->mRotateAndCropChanged = (mComposerOutput && !mOverrideToPortrait) ? false :
overrideAutoRotateAndCrop(captureRequest);
captureRequest->mAutoframingChanged = overrideAutoframing(captureRequest);
+ if (flags::inject_session_params()) {
+ injectSessionParams(captureRequest, mInjectedSessionParams);
+ }
}
// 'mNextRequests' will at this point contain either a set of HFR batched requests
@@ -3619,7 +3622,10 @@
if (res == OK) {
sp<Camera3Device> parent = mParent.promote();
if (parent != nullptr) {
- mReconfigured |= parent->reconfigureCamera(mLatestSessionParams, mStatusId);
+ if (parent->reconfigureCamera(mLatestSessionParams, mStatusId)) {
+ mForceNewRequestAfterReconfigure = true;
+ mReconfigured = true;
+ }
}
if (mNextRequests[0].captureRequest->mInputStream != nullptr) {
@@ -3751,12 +3757,20 @@
(mPrevRequest != captureRequest || triggersMixedIn ||
captureRequest->mRotateAndCropChanged ||
captureRequest->mAutoframingChanged ||
- testPatternChanged || settingsOverrideChanged) &&
+ testPatternChanged || settingsOverrideChanged ||
+ (flags::inject_session_params() && mForceNewRequestAfterReconfigure)) &&
// Request settings are all the same within one batch, so only treat the first
// request in a batch as new
!(batchedRequest && i > 0);
+
if (newRequest) {
std::set<std::string> cameraIdsWithZoom;
+
+ if (flags::inject_session_params() && mForceNewRequestAfterReconfigure) {
+ // This only needs to happen once.
+ mForceNewRequestAfterReconfigure = false;
+ }
+
/**
* HAL workaround:
* Insert a fake trigger ID if a trigger is set but no trigger ID is
@@ -4904,6 +4918,45 @@
return false;
}
+void Camera3Device::RequestThread::injectSessionParams(
+ const sp<CaptureRequest> &request,
+ const CameraMetadata& injectedSessionParams) {
+ CameraMetadata &requestMetadata = request->mSettingsList.begin()->metadata;
+ uint32_t tag_section;
+ camera_metadata_ro_entry entry;
+ for (auto tag : mSessionParamKeys) {
+ tag_section = tag >> 16;
+ if (tag_section < VENDOR_SECTION) {
+ // Only allow injection of vendor tags.
+ continue;
+ }
+ entry = injectedSessionParams.find(tag);
+ if (entry.count > 0) {
+ requestMetadata.update(entry);
+ }
+ }
+}
+
+status_t Camera3Device::RequestThread::setInjectedSessionParams(
+ const CameraMetadata& injectedSessionParams) {
+ ATRACE_CALL();
+ Mutex::Autolock l(mTriggerMutex);
+ mInjectedSessionParams = injectedSessionParams;
+ return OK;
+}
+
+status_t Camera3Device::injectSessionParams(const CameraMetadata& injectedSessionParams) {
+ ATRACE_CALL();
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+
+ if (mRequestThread == nullptr) {
+ return INVALID_OPERATION;
+ }
+
+ return mRequestThread->setInjectedSessionParams(injectedSessionParams);
+}
+
bool Camera3Device::RequestThread::overrideTestPattern(
const sp<CaptureRequest> &request) {
ATRACE_CALL();
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index bde7e1b..25f841a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -338,6 +338,11 @@
*/
status_t stopInjection();
+ /**
+ * Inject session params into the current client.
+ */
+ status_t injectSessionParams(const CameraMetadata& sessionParams);
+
protected:
status_t disconnectImpl();
static status_t removeFwkOnlyRegionKeys(CameraMetadata *request);
@@ -385,7 +390,6 @@
int mOperatingMode;
// Current session wide parameters
hardware::camera2::impl::CameraMetadataNative mSessionParams;
-
// Constant to use for no set operating mode
static const int NO_MODE = -1;
@@ -1005,6 +1009,12 @@
status_t setHalInterface(sp<HalInterface> newHalInterface);
+ status_t setInjectedSessionParams(const CameraMetadata& sessionParams);
+
+ void injectSessionParams(
+ const sp<CaptureRequest> &request,
+ const CameraMetadata& injectedSessionParams);
+
protected:
virtual bool threadLoop();
@@ -1185,6 +1195,8 @@
Vector<int32_t> mSessionParamKeys;
CameraMetadata mLatestSessionParams;
+ CameraMetadata mInjectedSessionParams;
+ bool mForceNewRequestAfterReconfigure;
std::map<int32_t, std::set<std::string>> mGroupIdPhysicalCameraMap;