Merge "AudioSystem: Reduce service timeout from 10s to 5s" into main
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
index 4dc5fb1..c24d51f 100644
--- a/apex/ld.config.txt
+++ b/apex/ld.config.txt
@@ -33,7 +33,7 @@
# TODO: replace the following when apex has a way to auto-generate this list
# namespace.default.link.platform.shared_libs = %LLNDK_LIBRARIES%
# namespace.default.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
+namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
###############################################################################
# "platform" namespace
@@ -138,7 +138,7 @@
# TODO: replace the following when apex has a way to auto-generate this list
# namespace.sphal.link.platform.shared_libs = %LLNDK_LIBRARIES%
# namespace.sphal.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
+namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
# Add a link for libz.so which is llndk on devices where VNDK is not enforced.
namespace.sphal.link.platform.shared_libs += libz.so
diff --git a/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index 3473780..ebb3305 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -32,7 +32,7 @@
const char *kCameraServiceDisabledProperty = "config.disable_cameraservice";
status_t CameraUtils::getRotationTransform(const CameraMetadata& staticInfo,
- int mirrorMode, /*out*/int32_t* transform) {
+ int mirrorMode, bool enableTransformInverseDisplay, /*out*/int32_t* transform) {
ALOGV("%s", __FUNCTION__);
if (transform == NULL) {
@@ -128,7 +128,9 @@
* aspect ratio, or the preview will end up looking non-uniformly
* stretched.
*/
- flags |= NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
+ if (enableTransformInverseDisplay) {
+ flags |= NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
+ }
ALOGV("%s: final transform = 0x%x", __FUNCTION__, flags);
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index ce6c2d3..6431737 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -157,6 +157,7 @@
* policy for default device context). Only virtual cameras would be exposed
* only for custom policy and only real cameras would be exposed for default
* policy.
+ * @param sharedMode Parameter specifying if the camera should be opened in shared mode.
*/
ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,
@utf8InCpp String cameraId,
@@ -164,7 +165,8 @@
int targetSdkVersion,
int rotationOverride,
in AttributionSourceState clientAttribution,
- int devicePolicy);
+ int devicePolicy,
+ boolean sharedMode);
/**
* Add listener for changes to camera device and flashlight state.
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl
index 9c8c88a..c0fd50e 100644
--- a/camera/aidl/android/hardware/ICameraServiceListener.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl
@@ -105,5 +105,6 @@
* will receive such callbacks.
*/
oneway void onCameraOpened(@utf8InCpp String cameraId, @utf8InCpp String clientPackageId, int deviceId);
+ oneway void onCameraOpenedInSharedMode(@utf8InCpp String cameraId, @utf8InCpp String clientPackageId, int deviceId, boolean primaryClient);
oneway void onCameraClosed(@utf8InCpp String cameraId, int deviceId);
}
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
index 58b19a3..49e9920 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl
@@ -50,4 +50,15 @@
oneway void onRepeatingRequestError(in long lastFrameNumber,
in int repeatingRequestId);
oneway void onRequestQueueEmpty();
+
+ /**
+ * Notify registered clients about client shared access priority changes when the camera device
+ * has been opened in shared mode.
+ *
+ * If the client priority changes from secondary to primary, then it can now
+ * create capture request and change the capture request parameters. If client priority
+ * changes from primary to secondary, that implies that another higher priority client is also
+ * accessing the camera in shared mode and is now the primary client.
+ */
+ oneway void onClientSharedAccessPriorityChanged(boolean primaryClient);
}
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 8e1fcc0..c1da126 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -68,6 +68,17 @@
const int CONSTRAINED_HIGH_SPEED_MODE = 1;
/**
+ * The shared operating mode for a camera device.
+ *
+ * <p>
+ * When in shared mode, the camera device can be opened and accessed by multiple applications
+ * simultaneously.
+ * </p>
+ *
+ */
+ const int SHARED_MODE = 2;
+
+ /**
* Start of custom vendor modes
*/
const int VENDOR_MODE_START = 0x8000;
@@ -194,4 +205,12 @@
*/
ICameraOfflineSession switchToOffline(in ICameraDeviceCallbacks callbacks,
in int[] offlineOutputIds);
+
+ /**
+ * Get the client status as primary or secondary when camera is opened in shared mode.
+ *
+ * @return true if this is primary client when camera is opened in shared mode.
+ * false if another higher priority client with primary access is also using the camera.
+ */
+ boolean isPrimaryClient();
}
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index daa2656..a89d7ca 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -34,6 +34,7 @@
namespace android {
const int OutputConfiguration::INVALID_ROTATION = -1;
+const int OutputConfiguration::ROTATION_0 = 0;
const int OutputConfiguration::INVALID_SET_ID = -1;
const std::vector<sp<IGraphicBufferProducer>>&
@@ -97,6 +98,10 @@
return mTimestampBase;
}
+int OutputConfiguration::getMirrorMode() const {
+ return mMirrorMode;
+}
+
int OutputConfiguration::getMirrorMode(sp<IGraphicBufferProducer> surface) const {
if (!flags::mirror_mode_shared_surfaces()) {
return mMirrorMode;
@@ -164,6 +169,29 @@
mUsage(0) {
}
+OutputConfiguration::OutputConfiguration(int surfaceType, int width, int height, int format,
+ int32_t colorSpace, int mirrorMode, bool useReadoutTimestamp, int timestampBase,
+ int dataspace, int64_t usage, int64_t streamusecase, std::string physicalCamId):
+ mRotation(ROTATION_0),
+ mSurfaceSetID(INVALID_SET_ID),
+ mSurfaceType(surfaceType),
+ mWidth(width),
+ mHeight(height),
+ mIsDeferred(false),
+ mIsShared(false),
+ mPhysicalCameraId(physicalCamId),
+ mIsMultiResolution(false),
+ mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
+ mColorSpace(colorSpace),
+ mStreamUseCase(streamusecase),
+ mTimestampBase(timestampBase),
+ mMirrorMode(mirrorMode),
+ mUseReadoutTimestamp(useReadoutTimestamp),
+ mFormat(format),
+ mDataspace(dataspace),
+ mUsage(usage){
+}
+
OutputConfiguration::OutputConfiguration(const android::Parcel& parcel) :
mRotation(INVALID_ROTATION),
mSurfaceSetID(INVALID_SET_ID) {
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index ebfd7d7..2feebb4 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -235,3 +235,24 @@
description: "Add new feature combination query version for Baklava"
bug: "370778206"
}
+
+flag {
+ namespace: "camera_platform"
+ name: "camera_multi_client"
+ is_exported: true
+ description: "add new feature to allow multiple clients to access the camera in shared mode"
+ bug: "265196098"
+ metadata {
+ purpose: PURPOSE_FEATURE
+ }
+}
+
+flag {
+ namespace: "camera_platform"
+ name: "query_process_state"
+ description: "In opChanged, query the process state from AM instead of relying on mUidPolicy"
+ bug: "378016494"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml
index 5d85909..d8264df 100644
--- a/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml
+++ b/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml
@@ -11,7 +11,7 @@
<hal format="aidl">
<name>android.frameworks.cameraservice.service</name>
- <version>2</version>
+ <version>3</version>
<interface>
<name>ICameraService</name>
<instance>default</instance>
diff --git a/camera/include/camera/CameraUtils.h b/camera/include/camera/CameraUtils.h
index d358407..766cac1 100644
--- a/camera/include/camera/CameraUtils.h
+++ b/camera/include/camera/CameraUtils.h
@@ -46,7 +46,7 @@
* Returns OK on success, or a negative error code.
*/
static status_t getRotationTransform(const CameraMetadata& staticInfo,
- int mirrorMode, /*out*/int32_t* transform);
+ int mirrorMode, bool enableTransformInverseDisplay, /*out*/int32_t* transform);
/**
* Check if the image data is VideoNativeHandleMetadata, that contains a native handle.
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 2049a31..671d065 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -33,6 +33,7 @@
class OutputConfiguration : public android::Parcelable {
public:
+ static const int ROTATION_0;
static const int INVALID_ROTATION;
static const int INVALID_SET_ID;
enum SurfaceType {
@@ -73,6 +74,7 @@
int64_t getStreamUseCase() const;
int getTimestampBase() const;
int getMirrorMode(sp<IGraphicBufferProducer> surface) const;
+ int getMirrorMode() const;
bool useReadoutTimestamp() const;
int getFormat() const;
int getDataspace() const;
@@ -107,6 +109,9 @@
int surfaceSetID = INVALID_SET_ID,
int surfaceType = SURFACE_TYPE_UNKNOWN, int width = 0,
int height = 0, bool isShared = false);
+ OutputConfiguration(int surfaceType, int width, int height, int format, int32_t colorSpace,
+ int mirrorMode, bool useReadoutTimestamp,int timestampBase, int dataspace,
+ int64_t usage, int64_t streamusecase, std::string physicalCamId);
bool operator == (const OutputConfiguration& other) const {
return ( mRotation == other.mRotation &&
@@ -211,6 +216,28 @@
bool mirrorModesEqual(const OutputConfiguration& other) const;
bool mirrorModesLessThan(const OutputConfiguration& other) const;
const std::vector<int32_t>& getMirrorModes() const {return mMirrorModeForProducers;}
+ bool sharedConfigEqual(const OutputConfiguration& other) const {
+ return (mRotation == other.mRotation &&
+ mSurfaceSetID == other.mSurfaceSetID &&
+ mSurfaceType == other.mSurfaceType &&
+ mWidth == other.mWidth &&
+ mHeight == other.mHeight &&
+ mIsDeferred == other.mIsDeferred &&
+ mIsShared == other.mIsShared &&
+ mPhysicalCameraId == other.mPhysicalCameraId &&
+ mIsMultiResolution == other.mIsMultiResolution &&
+ sensorPixelModesUsedEqual(other) &&
+ mDynamicRangeProfile == other.mDynamicRangeProfile &&
+ mColorSpace == other.mColorSpace &&
+ mStreamUseCase == other.mStreamUseCase &&
+ mTimestampBase == other.mTimestampBase &&
+ mMirrorMode == other.mMirrorMode &&
+ mUseReadoutTimestamp == other.mUseReadoutTimestamp &&
+ mFormat == other.mFormat &&
+ mDataspace == other.mDataspace &&
+ mUsage == other.mUsage);
+ }
+
private:
std::vector<sp<IGraphicBufferProducer>> mGbps;
int mRotation;
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 379c0b5..508808f 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -79,6 +79,7 @@
shared_libs: [
"android.companion.virtual.virtualdevice_aidl-cpp",
"android.companion.virtualdevice.flags-aconfig-cc",
+ "camera_platform_flags_c_lib",
"framework-permission-aidl-cpp",
"libandroid_runtime",
"libbinder",
@@ -147,8 +148,8 @@
shared_libs: [
"android.frameworks.cameraservice.common-V1-ndk",
- "android.frameworks.cameraservice.device-V2-ndk",
- "android.frameworks.cameraservice.service-V2-ndk",
+ "android.frameworks.cameraservice.device-V3-ndk",
+ "android.frameworks.cameraservice.service-V3-ndk",
"libbinder_ndk",
"libcamera_metadata",
"libcutils",
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index 92de1e4..58370e5 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -177,6 +177,34 @@
}
EXPORT
+camera_status_t ACameraCaptureSessionShared_startStreaming(
+ ACameraCaptureSession* /*session*/, ACameraCaptureSession_captureCallbacksV2* /*callbacks*/,
+ int /*numOutputWindows*/, ANativeWindow** /*window*/,
+ int* /*captureSequenceId*/) {
+ ATRACE_CALL();
+ // Todo: need to add implementation
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraCaptureSessionShared_logicalCamera_startStreaming(
+ ACameraCaptureSession* /*session*/,
+ ACameraCaptureSession_logicalCamera_captureCallbacksV2* /*callbacks*/,
+ int /*numOutputWindows*/, ANativeWindow** /*windows*/,
+ int* /*captureSequenceId*/) {
+ ATRACE_CALL();
+ // Todo: need to add implementation
+ return ACAMERA_OK;
+}
+
+EXPORT
+camera_status_t ACameraCaptureSessionShared_stopStreaming(ACameraCaptureSession* /*session*/) {
+ ATRACE_CALL();
+ // Todo: need to add implementation
+ return ACAMERA_OK;
+}
+
+EXPORT
camera_status_t ACameraCaptureSession_updateSharedOutput(ACameraCaptureSession* session,
ACaptureSessionOutput* output) {
ATRACE_CALL();
diff --git a/camera/ndk/NdkCameraManager.cpp b/camera/ndk/NdkCameraManager.cpp
index 1b3343e..28cc9af 100644
--- a/camera/ndk/NdkCameraManager.cpp
+++ b/camera/ndk/NdkCameraManager.cpp
@@ -27,6 +27,8 @@
#include "ndk_vendor/impl/ACameraManager.h"
#else
#include "impl/ACameraManager.h"
+#include <com_android_internal_camera_flags.h>
+namespace flags = com::android::internal::camera::flags;
#endif
#include "impl/ACameraMetadata.h"
@@ -159,6 +161,23 @@
}
EXPORT
+camera_status_t ACameraManager_isCameraDeviceSharingSupported(ACameraManager *mgr,
+ const char *cameraId, bool *isSharingSupported) {
+ ATRACE_CALL();
+ #ifndef __ANDROID_VNDK__
+ if (!flags::camera_multi_client()) {
+ return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+ }
+ #endif
+ if (mgr == nullptr || cameraId == nullptr || isSharingSupported == nullptr) {
+ ALOGE("%s: invalid argument! mgr %p cameraId %p isSharingSupported %p",
+ __FUNCTION__, mgr, cameraId, isSharingSupported);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return mgr->isCameraDeviceSharingSupported(cameraId, isSharingSupported);
+}
+
+EXPORT
camera_status_t ACameraManager_getCameraCharacteristics(
ACameraManager* mgr, const char* cameraId, ACameraMetadata** chars){
ATRACE_CALL();
@@ -188,7 +207,27 @@
__FUNCTION__, mgr, cameraId, callback, device);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- return mgr->openCamera(cameraId, callback, device);
+ bool primaryClient;
+ return mgr->openCamera(cameraId, /*sharedMode*/false, callback, device, &primaryClient);
+}
+
+EXPORT
+camera_status_t ACameraManager_openSharedCamera(
+ ACameraManager* mgr, const char* cameraId, ACameraDevice_StateCallbacks* callback,
+ /*out*/ACameraDevice** device, /*out*/bool* primaryClient) {
+ ATRACE_CALL();
+ #ifndef __ANDROID_VNDK__
+ if (!flags::camera_multi_client()) {
+ return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+ }
+ #endif
+ if (mgr == nullptr || cameraId == nullptr || callback == nullptr || device == nullptr ||
+ primaryClient == nullptr) {
+ ALOGE("%s: invalid argument! mgr %p cameraId %p callback %p device %p primary %p",
+ __FUNCTION__, mgr, cameraId, callback, device, primaryClient);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ }
+ return mgr->openCamera(cameraId, /*sharedMode*/true, callback, device, primaryClient);
}
#ifdef __ANDROID_VNDK__
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 1fa71f4..aed740f 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -26,6 +26,9 @@
#include "ACameraMetadata.h"
#include "ACaptureRequest.h"
#include "ACameraCaptureSession.h"
+#include <com_android_internal_camera_flags.h>
+
+namespace flags = com::android::internal::camera::flags;
ACameraDevice::~ACameraDevice() {
mDevice->stopLooperAndDisconnect();
@@ -57,12 +60,13 @@
const char* id,
ACameraDevice_StateCallbacks* cb,
sp<ACameraMetadata> chars,
- ACameraDevice* wrapper) :
+ ACameraDevice* wrapper, bool sharedMode) :
mCameraId(id),
mAppCallbacks(*cb),
mChars(chars),
mServiceCallback(new ServiceCallback(this)),
mWrapper(wrapper),
+ mSharedMode(sharedMode),
mInError(false),
mError(ACAMERA_OK),
mIdle(true),
@@ -970,6 +974,7 @@
case kWhatCaptureSeqAbort:
case kWhatCaptureBufferLost:
case kWhatPreparedCb:
+ case kWhatClientSharedAccessPriorityChanged:
ALOGV("%s: Received msg %d", __FUNCTION__, msg->what());
break;
case kWhatCleanUpSessions:
@@ -1007,6 +1012,32 @@
(*onDisconnected)(context, dev);
break;
}
+
+ case kWhatClientSharedAccessPriorityChanged:
+ {
+ if (!flags::camera_multi_client()) {
+ break;
+ }
+ ACameraDevice* dev;
+ found = msg->findPointer(kDeviceKey, (void**) &dev);
+ if (!found || dev == nullptr) {
+ ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
+ return;
+ }
+ ACameraDevice_ClientSharedAccessPriorityChangedCallback
+ onClientSharedAccessPriorityChanged;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onClientSharedAccessPriorityChanged);
+ if (!found) {
+ ALOGE("%s: Cannot find onClientSharedAccessPriorityChanged!", __FUNCTION__);
+ return;
+ }
+ if (onClientSharedAccessPriorityChanged == nullptr) {
+ return;
+ }
+ (*onClientSharedAccessPriorityChanged)(context, dev, dev->isPrimaryClient());
+ break;
+ }
+
case kWhatOnError:
{
ACameraDevice* dev;
@@ -1624,6 +1655,31 @@
}
binder::Status
+CameraDevice::ServiceCallback::onClientSharedAccessPriorityChanged(bool primaryClient) {
+ ALOGV("onClientSharedAccessPriorityChanged received. primaryClient = %d", primaryClient);
+ binder::Status ret = binder::Status::ok();
+ if (!flags::camera_multi_client()) {
+ return ret;
+ }
+ sp<CameraDevice> dev = mDevice.promote();
+ if (dev == nullptr) {
+ return ret; // device has been closed
+ }
+ Mutex::Autolock _l(dev->mDeviceLock);
+ if (dev->isClosed() || dev->mRemote == nullptr) {
+ return ret;
+ }
+ dev->setPrimaryClient(primaryClient);
+ sp<AMessage> msg = new AMessage(kWhatClientSharedAccessPriorityChanged, dev->mHandler);
+ msg->setPointer(kContextKey, dev->mAppCallbacks.context);
+ msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
+ msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onClientSharedAccessPriorityChanged);
+ msg->post();
+
+ return binder::Status::ok();
+}
+
+binder::Status
CameraDevice::ServiceCallback::onDeviceIdle() {
ALOGV("Camera is now idle");
binder::Status ret = binder::Status::ok();
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 2b9f327..d3aed4b 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -63,7 +63,7 @@
public:
CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
sp<ACameraMetadata> chars,
- ACameraDevice* wrapper);
+ ACameraDevice* wrapper, bool sharedMode);
~CameraDevice();
inline const char* getId() const { return mCameraId.c_str(); }
@@ -98,6 +98,7 @@
binder::Status onRequestQueueEmpty() override;
binder::Status onRepeatingRequestError(int64_t lastFrameNumber,
int32_t stoppedSequenceId) override;
+ binder::Status onClientSharedAccessPriorityChanged(bool isPrimaryClient) override;
private:
const wp<CameraDevice> mDevice;
};
@@ -113,6 +114,9 @@
// Stop the looper thread and unregister the handler
void stopLooperAndDisconnect();
+ void setPrimaryClient(bool isPrimary) {mIsPrimaryClient = isPrimary;};
+ bool isPrimaryClient() {return mIsPrimaryClient;};
+
private:
friend ACameraCaptureSession;
camera_status_t checkCameraClosedOrErrorLocked() const;
@@ -186,6 +190,8 @@
const sp<ACameraMetadata> mChars; // Camera characteristics
const sp<ServiceCallback> mServiceCallback;
ACameraDevice* mWrapper;
+ bool mSharedMode;
+ bool mIsPrimaryClient;
// stream id -> pair of (ANW* from application, OutputConfiguration used for camera service)
std::map<int, std::pair<ANativeWindow*, OutputConfiguration>> mConfiguredOutputs;
@@ -227,7 +233,8 @@
kWhatCaptureBufferLost, // onCaptureBufferLost
kWhatPreparedCb, // onWindowPrepared
// Internal cleanup
- kWhatCleanUpSessions // Cleanup cached sp<ACameraCaptureSession>
+ kWhatCleanUpSessions, // Cleanup cached sp<ACameraCaptureSession>
+ kWhatClientSharedAccessPriorityChanged
};
static const char* kContextKey;
static const char* kDeviceKey;
@@ -403,8 +410,8 @@
*/
struct ACameraDevice {
ACameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
- sp<ACameraMetadata> chars) :
- mDevice(new android::acam::CameraDevice(id, cb, chars, this)) {}
+ sp<ACameraMetadata> chars, bool sharedMode) :
+ mDevice(new android::acam::CameraDevice(id, cb, chars, this, sharedMode)) {}
~ACameraDevice();
@@ -445,6 +452,14 @@
mDevice->setRemoteDevice(remote);
}
+ inline void setPrimaryClient(bool isPrimary) {
+ mDevice->setPrimaryClient(isPrimary);
+ }
+
+ inline bool isPrimaryClient() {
+ return mDevice->isPrimaryClient();
+ }
+
private:
android::sp<android::acam::CameraDevice> mDevice;
};
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 53c4489..5dddd29 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -28,9 +28,11 @@
#include <memory>
#include "ACameraDevice.h"
#include "ACameraMetadata.h"
+#include <com_android_internal_camera_flags.h>
using namespace android::acam;
namespace vd_flags = android::companion::virtualdevice::flags;
+namespace flags = com::android::internal::camera::flags;
namespace android {
namespace acam {
@@ -860,10 +862,36 @@
}
camera_status_t
-ACameraManager::openCamera(
+ACameraManager::isCameraDeviceSharingSupported(
const char* cameraId,
+ /*out*/bool* isSharingSupported) {
+ if (!flags::camera_multi_client()) {
+ return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
+ }
+ sp<ACameraMetadata> spChars;
+ camera_status_t ret = getCameraCharacteristics(cameraId, &spChars);
+ if (ret != ACAMERA_OK) {
+ ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
+ __FUNCTION__, cameraId, ret);
+ return ret;
+ }
+
+ ACameraMetadata* chars = spChars.get();
+ ACameraMetadata_const_entry entry;
+ ret = ACameraMetadata_getConstEntry(chars, ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS,
+ &entry);
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+ *isSharingSupported = (entry.count > 0) ? true : false;
+ return ACAMERA_OK;
+}
+
+camera_status_t
+ACameraManager::openCamera(
+ const char* cameraId, bool sharedMode,
ACameraDevice_StateCallbacks* callback,
- /*out*/ACameraDevice** outDevice) {
+ /*out*/ACameraDevice** outDevice, /*out*/bool* primaryClient) {
sp<ACameraMetadata> chars;
camera_status_t ret = getCameraCharacteristics(cameraId, &chars);
Mutex::Autolock _l(mLock);
@@ -873,7 +901,7 @@
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- ACameraDevice* device = new ACameraDevice(cameraId, callback, chars);
+ ACameraDevice* device = new ACameraDevice(cameraId, callback, chars, sharedMode);
sp<hardware::ICameraService> cs = mGlobalManager->getCameraService();
if (cs == nullptr) {
@@ -898,7 +926,7 @@
binder::Status serviceRet = cs->connectDevice(
callbacks, cameraId, /*oomScoreOffset*/0,
targetSdkVersion, /*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_NONE,
- clientAttribution, static_cast<int32_t>(mDeviceContext.policy),
+ clientAttribution, static_cast<int32_t>(mDeviceContext.policy), sharedMode,
/*out*/&deviceRemote);
if (!serviceRet.isOk()) {
@@ -942,6 +970,14 @@
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
device->setRemoteDevice(deviceRemote);
+ if (flags::camera_multi_client() && sharedMode) {
+ binder::Status remoteRet = deviceRemote->isPrimaryClient(primaryClient);
+ if (!remoteRet.isOk()) {
+ delete device;
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ device->setPrimaryClient(*primaryClient);
+ }
*outDevice = device;
return ACAMERA_OK;
}
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index cb7a4ff..fffe037 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -138,6 +138,10 @@
virtual binder::Status onCameraOpened(const std::string&, const std::string&, int32_t) {
return binder::Status::ok();
}
+ virtual binder::Status onCameraOpenedInSharedMode(const std::string&, const std::string&,
+ int32_t, bool) {
+ return binder::Status::ok();
+ }
virtual binder::Status onCameraClosed(const std::string&, int32_t) {
return binder::Status::ok();
}
@@ -327,16 +331,17 @@
camera_status_t getCameraCharacteristics(
const char* cameraId, android::sp<ACameraMetadata>* characteristics);
- camera_status_t openCamera(const char* cameraId,
+ camera_status_t openCamera(const char* cameraId, bool sharedMode,
ACameraDevice_StateCallbacks* callback,
- /*out*/ACameraDevice** device);
+ /*out*/ACameraDevice** device, /*out*/bool* primaryClient);
void registerAvailabilityCallback(const ACameraManager_AvailabilityCallbacks* callback);
void unregisterAvailabilityCallback(const ACameraManager_AvailabilityCallbacks* callback);
void registerExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks* callback);
void unregisterExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks* callback);
-
+ camera_status_t isCameraDeviceSharingSupported(
+ const char* cameraId, bool* isSharingSupported);
private:
enum {
kCameraIdListNotInit = -1
diff --git a/camera/ndk/include/camera/NdkCameraCaptureSession.h b/camera/ndk/include/camera/NdkCameraCaptureSession.h
index 1400121..e73222b 100644
--- a/camera/ndk/include/camera/NdkCameraCaptureSession.h
+++ b/camera/ndk/include/camera/NdkCameraCaptureSession.h
@@ -1099,6 +1099,92 @@
camera_status_t ACameraCaptureSession_prepareWindow(
ACameraCaptureSession* session,
ANativeWindow *window) __INTRODUCED_IN(34);
+
+/**
+ * Request continuous streaming of a sequence of images for the shared capture session
+ * when more than one clients can open the same camera in shared mode by calling
+ * {@link ACameraManager_openSharedCamera}. In shared session, only primary clients can create
+ * a capture request and change capture parameters. Secondary clients can only request streaming of
+ * images by calling this api {@link ACameraCaptureSessionShared_startStreaming}. Calling this api
+ * for normal sessions when {@link ACameraManager_openCamera} is used to open the camera will throw
+ * {@link ACAMERA_ERROR_INVALID_OPERATION}.
+ *
+ * <p>With this method, the camera device will continually capture images, cycling through the
+ * settings in the list of {@link ACaptureRequest} specified by the primary client. If primary
+ * client does not have ongoing repeating request, camera service will use a capture request with
+ * default capture parameters for preview template.</p>
+ *
+ * <p>To stop the continuous streaming, call {@link ACameraCaptureSessionShared_stopStreaming}.</p>
+ *
+ * <p>Calling this method will replace an existing continuous streaming request.</p>
+ *
+ * @param sharedSession the shared capture session when camera is opened in
+ * shared mode.
+ * @param callbacks the {@link ACameraCaptureSession_captureCallbacks} to be associated with this
+ * capture sequence. No capture callback will be fired if callbacks is set to NULL.
+ * @param numOutputWindows number of native windows to be used for streaming. Must be at least 1.
+ * @param windows an array of {@link ANativeWindow} to be used for streaming. Length must be at
+ * least numOutputWindows.
+ * @param captureSequenceId the capture sequence ID associated with this capture method invocation
+ * will be stored here if this argument is not NULL and the method call succeeds.
+ * When this argument is set to NULL, the capture sequence ID will not be returned.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method succeeds. captureSequenceId will be filled
+ * if it is not NULL.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session or requests is NULL, or
+ * if numRequests < 1</li>
+ * <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error
+ * </li>
+ * <li>{@link ACAMERA_ERROR_INVALID_OPERATION} if the session passed is not a shared
+ * session</li>
+ * <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons</li>
+ * </ul>
+ */
+camera_status_t ACameraCaptureSessionShared_startStreaming(
+ ACameraCaptureSession* sharedSession, ACameraCaptureSession_captureCallbacksV2 *callbacks,
+ int numOutputWindows, ANativeWindow **window,
+ int *captureSequenceId) __INTRODUCED_IN(36);
+
+/**
+ * This has the same functionality as ACameraCaptureSessionShared_startStreaming, with added
+ * support for logical multi-camera where the capture callbacks supports result metadata for
+ * physical cameras.
+ */
+camera_status_t ACameraCaptureSessionShared_logicalCamera_startStreaming(
+ ACameraCaptureSession* sharedSession,
+ ACameraCaptureSession_logicalCamera_captureCallbacksV2 *callbacks,
+ int numOutputWindows, ANativeWindow **windows,
+ int *captureSequenceId) __INTRODUCED_IN(36);
+
+/**
+ * Cancel any ongoing streaming started by {@link ACameraCaptureSessionShared_startStreaming}.
+ * Calling this api does not effect any streaming requests submitted by other clients who have
+ * opened the camera in shared mode. Calling this api for normal sessions when
+ * {@link ACameraManager_openCamera} is used to open the camera will throw
+ * {@link ACAMERA_ERROR_INVALID_OPERATION}.
+ *
+ * @param sharedSession the capture session of interest
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if session is NULL.</li>
+ * <li>{@link ACAMERA_ERROR_SESSION_CLOSED} if the capture session has been closed</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error
+ * </li>
+ * <li>{@link ACAMERA_ERROR_INVALID_OPERATION} if the session passed is not a shared
+ * session</li>
+ * <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons</li>
+ * </ul>
+ */
+camera_status_t ACameraCaptureSessionShared_stopStreaming(
+ ACameraCaptureSession *sharedSession
+) __INTRODUCED_IN(36);
__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 fbd0ee1..8c7eb1f 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -125,6 +125,18 @@
typedef void (*ACameraDevice_ErrorStateCallback)(void* context, ACameraDevice* device, int error);
/**
+ * Client access priorities changed callbacks to be used in {@link ACameraDevice_StateCallbacks}
+ * when camera is opened in shared mode.
+ *
+ * @param context The optional context in {@link ACameraDevice_StateCallbacks} will be passed to
+ * this callback.
+ * @param device The {@link ACameraDevice} whose access priorities has been changed.
+ * @param isPrimaryClient whether the client is primary client.
+ */
+typedef void (*ACameraDevice_ClientSharedAccessPriorityChangedCallback)(void* context,
+ ACameraDevice* device, bool isPrimaryClient);
+
+/**
* Applications' callbacks for camera device state changes, register with
* {@link ACameraManager_openCamera}.
*/
@@ -163,6 +175,17 @@
*
*/
ACameraDevice_ErrorStateCallback onError;
+
+ /**
+ * Notify registered clients about client shared access priority changes when the camera device
+ * has been opened in shared mode.
+ *
+ * If the client priority changes from secondary to primary, then it can now
+ * create capture request and change the capture request parameters. If client priority
+ * changes from primary to secondary, that implies that another higher priority client is also
+ * accessing the camera in shared mode and is now the primary client.
+ */
+ ACameraDevice_ClientSharedAccessPriorityChangedCallback onClientSharedAccessPriorityChanged;
} ACameraDevice_StateCallbacks;
/**
@@ -671,7 +694,9 @@
* <li>{@link ACAMERA_OK} if the method call succeeds. The created capture session will be
* filled in session argument.</li>
* <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if any of device, outputs, callbacks or
- * session is NULL.</li>
+ * session is NULL or if the outputs does not match the predefined
+ * shared session configuration when camera is opened in shared mode.
+ * </li>
* <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if the camera device is closed.</li>
* <li>{@link ACAMERA_ERROR_CAMERA_DEVICE} if the camera device encounters fatal error.</li>
* <li>{@link ACAMERA_ERROR_CAMERA_SERVICE} if the camera service encounters fatal error.</li>
diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h
index b4f3bf1..a9b0174 100644
--- a/camera/ndk/include/camera/NdkCameraManager.h
+++ b/camera/ndk/include/camera/NdkCameraManager.h
@@ -293,6 +293,46 @@
/*out*/ACameraDevice** device) __INTRODUCED_IN(24);
/**
+ * Open a shared connection to a camera with the given ID. The opened camera device will be
+ * returned in the `device` parameter. The behavior of this method matches that of
+ * {@link ACameraManager_openCamera(ACameraManager*, const char*, ACameraDevice_StateCallbacks*,
+ * ACameraDevice**)} except that it opens the camera in shared mode so that more
+ * than one client can access the camera at the same time.
+ *
+ * <p>Processes need to have android.permission.SYSTEM_CAMERA in addition to
+ * android.permission.CAMERA in order to connect to this camera device in shared
+ * mode.</p>
+ *
+ * @param manager the {@link ACameraManager} of interest.
+ * @param cameraId the ID string of the camera device to be opened.
+ * @param callback the {@link ACameraDevice_StateCallbacks} associated with the opened camera
+ * device.
+ * @param device the opened {@link ACameraDevice} will be filled here if the method call succeeds.
+ * @param primaryClient will return as true if the client is primaryClient.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if manager, cameraId, callback, or device
+ * is NULL, or cameraId does not match any camera devices connected.</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_DISCONNECTED} if connection to camera service fails.</li>
+ * <li>{@link ACAMERA_ERROR_NOT_ENOUGH_MEMORY} if allocating memory fails.</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_IN_USE} if camera device is being used by a higher
+ * priority camera API client.</li>
+ * <li>{@link ACAMERA_ERROR_MAX_CAMERA_IN_USE} if the system-wide limit for number of open
+ * cameras or camera resources has been reached, and more camera devices cannot be
+ * opened until previous instances are closed.</li>
+ * <li>{@link ACAMERA_ERROR_CAMERA_DISABLED} if the camera is disabled due to a device
+ * policy, and cannot be opened.</li>
+ * <li>{@link ACAMERA_ERROR_PERMISSION_DENIED} if the application does not have permission
+ * to open camera.</li>
+ * <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ */
+camera_status_t ACameraManager_openSharedCamera(
+ ACameraManager* manager, const char* cameraId,
+ ACameraDevice_StateCallbacks* callback,
+ /*out*/ACameraDevice** device,/*out*/bool* isPrimaryClient) __INTRODUCED_IN(36);
+
+/**
* Definition of camera access permission change callback.
*
* <p>Notification that camera access priorities have changed and the camera may
@@ -397,6 +437,27 @@
ACameraManager* manager,
const ACameraManager_ExtendedAvailabilityCallbacks* callback) __INTRODUCED_IN(29);
+
+/**
+ * Checks if a camera can be opened in shared mode by multiple clients.
+ *
+ * @param manager the {@link ACameraManager} of interest.
+ * @param cameraId the ID string of the camera device of interest.
+ * @param isSharingSupported output will be filled here if the method succeeds.
+ * This will be true if camera can be opened in shared mode, false
+ * otherwise.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if any parameter is not
+ * valid.</li>
+ * </ul>
+ */
+camera_status_t ACameraManager_isCameraDeviceSharingSupported(
+ ACameraManager *manager,
+ const char *cameraId,
+ bool *isSharingSupported) __INTRODUCED_IN(36);
+
#ifdef __ANDROID_VNDK__
/**
* Retrieve the tag value, given the tag name and camera id.
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index b792de0..fc6b932 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -91,6 +91,7 @@
ACAMERA_AUTOMOTIVE_LENS,
ACAMERA_EXTENSION,
ACAMERA_JPEGR,
+ ACAMERA_SHARED_SESSION,
ACAMERA_SECTION_COUNT,
ACAMERA_VENDOR = 0x8000
@@ -138,6 +139,7 @@
ACAMERA_AUTOMOTIVE_LENS_START = ACAMERA_AUTOMOTIVE_LENS << 16,
ACAMERA_EXTENSION_START = ACAMERA_EXTENSION << 16,
ACAMERA_JPEGR_START = ACAMERA_JPEGR << 16,
+ ACAMERA_SHARED_SESSION_START = ACAMERA_SHARED_SESSION << 16,
ACAMERA_VENDOR_START = ACAMERA_VENDOR << 16
} acamera_metadata_section_start_t;
@@ -9750,6 +9752,28 @@
} acamera_metadata_enum_android_control_low_light_boost_state_t;
+// ACAMERA_CONTROL_ZOOM_METHOD
+typedef enum acamera_metadata_enum_acamera_control_zoom_method {
+ /**
+ * <p>The camera device automatically detects whether the application does zoom with
+ * ACAMERA_SCALER_CROP_REGION or ACAMERA_CONTROL_ZOOM_RATIO, and in turn decides which
+ * metadata tag reflects the effective zoom level.</p>
+ *
+ * @see ACAMERA_CONTROL_ZOOM_RATIO
+ * @see ACAMERA_SCALER_CROP_REGION
+ */
+ ACAMERA_CONTROL_ZOOM_METHOD_AUTO = 0,
+
+ /**
+ * <p>The application intends to control zoom via ACAMERA_CONTROL_ZOOM_RATIO, and
+ * the effective zoom level is reflected by ACAMERA_CONTROL_ZOOM_RATIO in capture results.</p>
+ *
+ * @see ACAMERA_CONTROL_ZOOM_RATIO
+ */
+ ACAMERA_CONTROL_ZOOM_METHOD_ZOOM_RATIO = 1,
+
+} acamera_metadata_enum_android_control_zoom_method_t;
+
// ACAMERA_CONTROL_AE_PRIORITY_MODE
typedef enum acamera_metadata_enum_acamera_control_ae_priority_mode {
/**
@@ -12057,6 +12081,7 @@
+
__END_DECLS
#endif /* _NDK_CAMERA_METADATA_TAGS_H */
diff --git a/camera/ndk/libcamera2ndk.map.txt b/camera/ndk/libcamera2ndk.map.txt
index 7d7868b..60d4775 100644
--- a/camera/ndk/libcamera2ndk.map.txt
+++ b/camera/ndk/libcamera2ndk.map.txt
@@ -28,6 +28,8 @@
ACameraManager_getCameraCharacteristics;
ACameraManager_getCameraIdList;
ACameraManager_openCamera;
+ ACameraManager_openSharedCamera; # systemapi introduced=36
+ ACameraManager_isCameraDeviceSharingSupported; # systemapi introduced=36
ACameraManager_registerAvailabilityCallback;
ACameraManager_unregisterAvailabilityCallback;
ACameraManager_registerExtendedAvailabilityCallback; # introduced=29
@@ -72,6 +74,9 @@
ACaptureSessionSharedOutput_remove; # introduced=28
ACaptureSessionPhysicalOutput_create; # introduced=29
ACaptureSessionOutput_free;
+ ACameraCaptureSessionShared_startStreaming; # systemapi introduced=36
+ ACameraCaptureSessionShared_logicalCamera_startStreaming; # systemapi introduced=36
+ ACameraCaptureSessionShared_stopStreaming; # systemapi introduced=36
local:
*;
};
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 9ed8197..d3a8e0d 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -85,11 +85,12 @@
const char* id,
ACameraDevice_StateCallbacks* cb,
sp<ACameraMetadata> chars,
- ACameraDevice* wrapper) :
+ ACameraDevice* wrapper, bool sharedMode) :
mCameraId(id),
mAppCallbacks(*cb),
mChars(std::move(chars)),
mWrapper(wrapper),
+ mSharedMode(sharedMode),
mInError(false),
mError(ACAMERA_OK),
mIdle(true),
@@ -960,6 +961,7 @@
case kWhatCaptureSeqAbort:
case kWhatCaptureBufferLost:
case kWhatPreparedCb:
+ case kWhatClientSharedAccessPriorityChanged:
ALOGV("%s: Received msg %d", __FUNCTION__, msg->what());
break;
case kWhatCleanUpSessions:
@@ -997,6 +999,28 @@
(*onDisconnected)(context, dev);
break;
}
+ case kWhatClientSharedAccessPriorityChanged:
+ {
+ ACameraDevice* dev;
+ found = msg->findPointer(kDeviceKey, (void**) &dev);
+ if (!found || dev == nullptr) {
+ ALOGE("%s: Cannot find device pointer!", __FUNCTION__);
+ return;
+ }
+ ACameraDevice_ClientSharedAccessPriorityChangedCallback
+ onClientSharedAccessPriorityChanged;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onClientSharedAccessPriorityChanged);
+ if (!found) {
+ ALOGE("%s: Cannot find onClientSharedAccessPriorityChanged!", __FUNCTION__);
+ return;
+ }
+ if (onClientSharedAccessPriorityChanged == nullptr) {
+ return;
+ }
+ (*onClientSharedAccessPriorityChanged)(context, dev, dev->isPrimaryClient());
+ break;
+ }
+
case kWhatOnError:
{
ACameraDevice* dev;
@@ -1614,6 +1638,28 @@
return ScopedAStatus::ok();
}
+ScopedAStatus CameraDevice::ServiceCallback::onClientSharedAccessPriorityChanged(
+ bool primaryClient) {
+ ALOGV("onClientSharedAccessPriorityChanged received. primaryClient = %d", primaryClient);
+ ScopedAStatus ret = ScopedAStatus::ok();
+ std::shared_ptr<CameraDevice> dev = mDevice.lock();
+ if (dev == nullptr) {
+ return ret; // device has been closed
+ }
+ Mutex::Autolock _l(dev->mDeviceLock);
+ if (dev->isClosed() || dev->mRemote == nullptr) {
+ return ret;
+ }
+ dev->setPrimaryClient(primaryClient);
+ sp<AMessage> msg = new AMessage(kWhatClientSharedAccessPriorityChanged, dev->mHandler);
+ msg->setPointer(kContextKey, dev->mAppCallbacks.context);
+ msg->setPointer(kDeviceKey, (void*) dev->getWrapper());
+ msg->setPointer(kCallbackFpKey, (void*) dev->mAppCallbacks.onClientSharedAccessPriorityChanged);
+ msg->post();
+
+ return ScopedAStatus::ok();
+}
+
ScopedAStatus CameraDevice::ServiceCallback::onDeviceIdle() {
ALOGV("Camera is now idle");
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index b771d47..6ba30bb 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -95,7 +95,7 @@
public:
CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
sp<ACameraMetadata> chars,
- ACameraDevice* wrapper);
+ ACameraDevice* wrapper, bool sharedMode);
~CameraDevice();
// Called to initialize fields that require shared_ptr to `this`
@@ -136,6 +136,7 @@
const CaptureResultExtras& in_resultExtras,
const std::vector<PhysicalCaptureResultInfo>&
in_physicalCaptureResultInfos) override;
+ ndk::ScopedAStatus onClientSharedAccessPriorityChanged(bool isPrimaryClient) override;
private:
camera_status_t readOneResultMetadata(const CaptureMetadataInfo& captureMetadataInfo,
@@ -154,6 +155,8 @@
// Stop the looper thread and unregister the handler
void stopLooperAndDisconnect();
+ void setPrimaryClient(bool isPrimary) {mIsPrimaryClient = isPrimary;};
+ bool isPrimaryClient() {return mIsPrimaryClient;};
private:
friend ACameraCaptureSession;
@@ -232,6 +235,8 @@
const sp<ACameraMetadata> mChars; // Camera characteristics
std::shared_ptr<ServiceCallback> mServiceCallback;
ACameraDevice* mWrapper;
+ bool mSharedMode;
+ bool mIsPrimaryClient;
// stream id -> pair of (ACameraWindowType* from application, OutputConfiguration used for
// camera service)
@@ -274,7 +279,8 @@
kWhatCaptureBufferLost, // onCaptureBufferLost
kWhatPreparedCb, // onPrepared
// Internal cleanup
- kWhatCleanUpSessions // Cleanup cached sp<ACameraCaptureSession>
+ kWhatCleanUpSessions, // Cleanup cached sp<ACameraCaptureSession>
+ kWhatClientSharedAccessPriorityChanged
};
static const char* kContextKey;
static const char* kDeviceKey;
@@ -434,9 +440,9 @@
*/
struct ACameraDevice {
ACameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
- sp<ACameraMetadata> chars) :
+ sp<ACameraMetadata> chars, bool sharedMode) :
mDevice(std::make_shared<android::acam::CameraDevice>(id, cb,
- std::move(chars), this)) {
+ std::move(chars), this, sharedMode)) {
mDevice->init();
}
@@ -481,6 +487,13 @@
inline bool setDeviceMetadataQueues() {
return mDevice->setDeviceMetadataQueues();
}
+ inline void setPrimaryClient(bool isPrimary) {
+ mDevice->setPrimaryClient(isPrimary);
+ }
+ inline bool isPrimaryClient() {
+ return mDevice->isPrimaryClient();
+ }
+
private:
std::shared_ptr<android::acam::CameraDevice> mDevice;
};
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index 5b69f5c..c34c4bd 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -789,10 +789,33 @@
}
camera_status_t
-ACameraManager::openCamera(
+ACameraManager::isCameraDeviceSharingSupported(
const char* cameraId,
+ /*out*/bool* isSharingSupported) {
+ sp<ACameraMetadata> spChars;
+ camera_status_t ret = getCameraCharacteristics(cameraId, &spChars);
+ if (ret != ACAMERA_OK) {
+ ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
+ __FUNCTION__, cameraId, ret);
+ return ret;
+ }
+
+ ACameraMetadata* chars = spChars.get();
+ ACameraMetadata_const_entry entry;
+ ret = ACameraMetadata_getConstEntry(chars, ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS,
+ &entry);
+ if (ret != ACAMERA_OK) {
+ return ret;
+ }
+ *isSharingSupported = (entry.count > 0) ? true : false;
+ return ACAMERA_OK;
+}
+
+camera_status_t
+ACameraManager::openCamera(
+ const char* cameraId, bool sharedMode,
ACameraDevice_StateCallbacks* callback,
- /*out*/ACameraDevice** outDevice) {
+ /*out*/ACameraDevice** outDevice, /*out*/bool* isPrimaryClient) {
sp<ACameraMetadata> rawChars;
camera_status_t ret = getCameraCharacteristics(cameraId, &rawChars);
Mutex::Autolock _l(mLock);
@@ -802,7 +825,7 @@
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(rawChars));
+ ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(rawChars), sharedMode);
std::shared_ptr<ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
if (cs == nullptr) {
@@ -813,11 +836,18 @@
std::shared_ptr<BnCameraDeviceCallback> deviceCallback = device->getServiceCallback();
std::shared_ptr<ICameraDeviceUser> deviceRemote;
+ ScopedAStatus serviceRet;
// No way to get package name from native.
// Send a zero length package name and let camera service figure it out from UID
- ScopedAStatus serviceRet = cs->connectDevice(deviceCallback,
- std::string(cameraId), &deviceRemote);
+ if (sharedMode) {
+ serviceRet = cs->connectDeviceV2(deviceCallback,
+ std::string(cameraId), sharedMode, &deviceRemote);
+ } else {
+ serviceRet = cs->connectDevice(deviceCallback,
+ std::string(cameraId), &deviceRemote);
+ }
+
if (!serviceRet.isOk()) {
if (serviceRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
Status errStatus = static_cast<Status>(serviceRet.getServiceSpecificError());
@@ -840,6 +870,13 @@
}
device->setRemoteDevice(deviceRemote);
+ if (sharedMode) {
+ ScopedAStatus remoteRet = deviceRemote->isPrimaryClient(isPrimaryClient);
+ if (!remoteRet.isOk()) {
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ device->setPrimaryClient(*isPrimaryClient);
+ }
device->setDeviceMetadataQueues();
*outDevice = device;
return ACAMERA_OK;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h
index 5688e76..e9973e6 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h
@@ -261,9 +261,9 @@
camera_status_t getCameraCharacteristics(
const char* cameraId, android::sp<ACameraMetadata>* characteristics);
- camera_status_t openCamera(const char* cameraId,
- ACameraDevice_StateCallbacks* callback,
- /*out*/ACameraDevice** device);
+ camera_status_t openCamera(const char* cameraId, bool sharedMode,
+ ACameraDevice_StateCallbacks* callback, /*out*/ACameraDevice** device,
+ /*out*/bool* primaryClient);
camera_status_t getTagFromName(const char *cameraId, const char *name, uint32_t *tag);
void registerAvailabilityCallback(const ACameraManager_AvailabilityCallbacks* callback);
void unregisterAvailabilityCallback(const ACameraManager_AvailabilityCallbacks* callback);
@@ -271,6 +271,8 @@
const ACameraManager_ExtendedAvailabilityCallbacks* callback);
void unregisterExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks* callback);
+ camera_status_t isCameraDeviceSharingSupported(const char *cameraId,
+ bool *isSharingSupported);
private:
enum {
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 5135b5d..4384df9 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -130,6 +130,15 @@
return binder::Status::ok();
}
+ virtual binder::Status onCameraOpenedInSharedMode(
+ [[maybe_unused]] const std::string& /*cameraId*/,
+ [[maybe_unused]] const std::string& /*clientPackageName*/,
+ [[maybe_unused]] int32_t /*deviceId*/,
+ [[maybe_unused]] bool /*isPrimaryClient*/) override {
+ // No op
+ return binder::Status::ok();
+ }
+
bool waitForNumCameras(size_t num) const {
Mutex::Autolock l(mLock);
@@ -281,6 +290,12 @@
return binder::Status::ok();
}
+ virtual binder::Status onClientSharedAccessPriorityChanged(
+ [[maybe_unused]] bool /*isPrimaryClient*/) {
+ // No-op
+ return binder::Status::ok();
+ }
+
// Test helper functions:
bool hadError() const {
@@ -402,7 +417,8 @@
res = service->connectDevice(callbacks, cameraId,
/*oomScoreOffset*/ 0,
/*targetSdkVersion*/__ANDROID_API_FUTURE__,
- /*overrideToPortrait*/false, clientAttribution, /*devicePolicy*/0, /*out*/&device);
+ /*overrideToPortrait*/false, clientAttribution, /*devicePolicy*/0,
+ /*sharedMode*/false, /*out*/&device);
EXPECT_TRUE(res.isOk()) << res;
ASSERT_NE(nullptr, device.get());
device->disconnect();
@@ -451,7 +467,7 @@
/*oomScoreOffset*/ 0,
/*targetSdkVersion*/__ANDROID_API_FUTURE__,
/*overrideToPortrait*/false, clientAttribution, /*devicePolicy*/0,
- /*out*/&device);
+ /*sharedMode*/false, /*out*/&device);
EXPECT_TRUE(res.isOk()) << res;
}
auto p = std::make_pair(callbacks, device);
diff --git a/camera/tests/fuzzer/camera_utils_fuzzer.cpp b/camera/tests/fuzzer/camera_utils_fuzzer.cpp
index c816f82..ca0a06f 100644
--- a/camera/tests/fuzzer/camera_utils_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_utils_fuzzer.cpp
@@ -75,6 +75,7 @@
CameraUtils::getRotationTransform(
staticMetadata, mFDP->ConsumeIntegral<int32_t>() /* mirrorMode */,
+ true /*enableTransformInverseDisplay*/,
&transform /*out*/);
},
[&]() { CameraUtils::isCameraServiceDisabled(); },
diff --git a/drm/libmediadrm/DrmHalHidl.cpp b/drm/libmediadrm/DrmHalHidl.cpp
index c8c6e8e..33ea5ea 100644
--- a/drm/libmediadrm/DrmHalHidl.cpp
+++ b/drm/libmediadrm/DrmHalHidl.cpp
@@ -339,7 +339,7 @@
DrmUtils::LOG2BI("makeDrmFactories: using default passthrough drm instance");
factories.push_back(passthrough);
} else {
- DrmUtils::LOG2BE("Failed to find passthrough drm factories");
+ DrmUtils::LOG2BW("Failed to find passthrough drm factories");
}
}
return factories;
diff --git a/media/audio/aconfig/Android.bp b/media/audio/aconfig/Android.bp
index 2da6758..cab126f 100644
--- a/media/audio/aconfig/Android.bp
+++ b/media/audio/aconfig/Android.bp
@@ -120,6 +120,7 @@
"//frameworks/base/api",
"//frameworks/base/core/res",
],
+ exportable: true,
}
aconfig_declarations {
@@ -152,6 +153,20 @@
}
java_aconfig_library {
+ name: "android.media.audio-aconfig-exported-java",
+ aconfig_declarations: "android.media.audio-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+ min_sdk_version: "Tiramisu",
+ mode: "exported",
+ apex_available: [
+ "com.android.btservices",
+ ],
+ visibility: [
+ "//packages/modules/Bluetooth:__subpackages__",
+ ],
+}
+
+java_aconfig_library {
name: "android.media.audiopolicy-aconfig-java",
aconfig_declarations: "android.media.audiopolicy-aconfig",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
diff --git a/media/audio/aconfig/audio_framework.aconfig b/media/audio/aconfig/audio_framework.aconfig
index ae7eb36..1450417 100644
--- a/media/audio/aconfig/audio_framework.aconfig
+++ b/media/audio/aconfig/audio_framework.aconfig
@@ -120,6 +120,14 @@
}
flag {
+ name: "hardening_permission_spa"
+ is_exported: true
+ namespace: "media_audio"
+ description: "Flag for special app access impl for hardening."
+ bug: "376480814"
+}
+
+flag {
name: "iamf_definitions_api"
is_exported: true
namespace: "media_audio"
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
index 4ec26d6..44a8dd1 100644
--- a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
+++ b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
@@ -139,8 +139,8 @@
addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
.withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
.withFields({
- C2F(mSize, width).inRange(2, 2048, 2),
- C2F(mSize, height).inRange(2, 2048, 2),
+ C2F(mSize, width).inRange(2, 4096, 2),
+ C2F(mSize, height).inRange(2, 4096, 2),
})
.withSetter(MaxPictureSizeSetter, mSize)
.build());
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index 318f093..83cbe47 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -69,8 +69,8 @@
DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
.withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
.withFields({
- C2F(mSize, width).inRange(2, 2048),
- C2F(mSize, height).inRange(2, 2048),
+ C2F(mSize, width).inRange(2, 4096),
+ C2F(mSize, height).inRange(2, 4096),
})
.withSetter(SizeSetter)
.build());
@@ -167,8 +167,8 @@
DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
.withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
.withFields({
- C2F(mSize, width).inRange(2, 2048, 2),
- C2F(mSize, height).inRange(2, 2048, 2),
+ C2F(mSize, width).inRange(2, 4096, 2),
+ C2F(mSize, height).inRange(2, 4096, 2),
})
.withSetter(MaxPictureSizeSetter, mSize)
.build());
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 665f9fc..17dfe9c 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -997,7 +997,7 @@
return -1;
}
- if (toUsage != graphicBuffer->getUsage()) {
+ if ((toUsage & graphicBuffer->getUsage()) != toUsage) {
sp<GraphicBuffer> newBuffer = new GraphicBuffer(
graphicBuffer->handle, GraphicBuffer::CLONE_HANDLE,
graphicBuffer->width, graphicBuffer->height, graphicBuffer->format,
diff --git a/media/janitors/media_solutions_OWNERS b/media/janitors/media_solutions_OWNERS
index 95c2b97..004fa30 100644
--- a/media/janitors/media_solutions_OWNERS
+++ b/media/janitors/media_solutions_OWNERS
@@ -17,3 +17,8 @@
# MediaRouter and native mirroring only:
aquilescanta@google.com
+
+# Emergency rollbacks and fixes outside LON timezone
+jmtrivi@google.com # US-MTV
+lajos@google.com # US-MTV
+scottnien@google.com # TW-NTC
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
index a1ed6a0..3b50744 100644
--- a/media/libaaudio/fuzzer/Android.bp
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -62,8 +62,6 @@
"libaudioclient",
"libaudioutils",
"libbase_ndk",
- "libcgrouprc",
- "libcgrouprc_format",
"libcutils",
"libjsoncpp",
"liblog",
diff --git a/media/libaudioclient/aidl/fuzzer/Android.bp b/media/libaudioclient/aidl/fuzzer/Android.bp
index a215c0b..14e528f 100644
--- a/media/libaudioclient/aidl/fuzzer/Android.bp
+++ b/media/libaudioclient/aidl/fuzzer/Android.bp
@@ -24,8 +24,6 @@
"android.hardware.audio.common@7.0-enums",
"audiopermissioncontroller",
"libaudiomockhal",
- "libcgrouprc",
- "libcgrouprc_format",
"libfakeservicemanager",
"libjsoncpp",
"libmediametricsservice",
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index 8bca8df..65ada70 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -37,8 +37,6 @@
"effect-aidl-cpp",
"libaudioclient",
"libbase",
- "libcgrouprc",
- "libcgrouprc_format",
"libcutils",
"libjsoncpp",
"liblog",
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index ddf14a3..3941280 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -107,7 +107,6 @@
"framework-permission-aidl-cpp",
"libaudioutils",
"libbase",
- "libcgrouprc",
"libdl",
"libmedia",
"libmedia_helper",
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index fcdaff9..e413241 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -33,6 +33,7 @@
"liblog",
],
shared_libs: [
+ "camera_platform_flags_c_lib",
"framework-permission-aidl-cpp",
"libbinder",
"libbinder_ndk",
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index a544066..efbd682 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1192,6 +1192,19 @@
return new PersistentSurface(bufferProducer, bufferSource);
}
+//static
+status_t MediaCodec::getGloballyAvailableResources(std::vector<GlobalResourceInfo>& resources) {
+ resources.clear();
+ // Make sure codec availability feature is on.
+ if (!android::media::codec::codec_availability()) {
+ return ERROR_UNSUPPORTED;
+ }
+ // TODO: For now this is just an empty function.
+ // The actual implementation should use component store to query the
+ // available resources from hal, and fill in resources with the same.
+ return ERROR_UNSUPPORTED;
+}
+
// GenerateCodecId generates a 64bit Random ID for each codec that is created.
// The Codec ID is generated as:
// - A process-unique random high 32bits
@@ -1298,7 +1311,12 @@
CHECK_EQ(mState, UNINITIALIZED);
mResourceManagerProxy->removeClient();
- flushMediametrics();
+ flushMediametrics(); // this deletes mMetricsHandle
+ // don't keep the last metrics handle around
+ if (mLastMetricsHandle != 0) {
+ mediametrics_delete(mLastMetricsHandle);
+ mLastMetricsHandle = 0;
+ }
// clean any saved metrics info we stored as part of configure()
if (mConfigureMsg != nullptr) {
@@ -1309,7 +1327,7 @@
}
}
-// except for in constructor, called from the looper thread (and therefore mutexed)
+// except for in constructor, called from the looper thread (and therefore not mutexed)
void MediaCodec::initMediametrics() {
if (mMetricsHandle == 0) {
mMetricsHandle = mediametrics_create(kCodecKeyName);
@@ -1335,6 +1353,7 @@
mInputBufferCounter = 0;
}
+ mSubsessionCount = 0;
mLifetimeStartNs = systemTime(SYSTEM_TIME_MONOTONIC);
resetMetricsFields();
}
@@ -1346,6 +1365,17 @@
mReliabilityContextMetrics = ReliabilityContextMetrics();
}
+// always called from the looper thread (and therefore not mutexed)
+void MediaCodec::resetSubsessionMetricsFields() {
+ mBytesEncoded = 0;
+ mFramesEncoded = 0;
+ mFramesInput = 0;
+ mBytesInput = 0;
+ mEarliestEncodedPtsUs = INT64_MAX;
+ mLatestEncodedPtsUs = INT64_MIN;
+}
+
+// always called from the looper thread
void MediaCodec::updateMediametrics() {
if (mMetricsHandle == 0) {
ALOGV("no metrics handle found");
@@ -1710,6 +1740,7 @@
}
}
+// except for in destructor, called from the looper thread
void MediaCodec::flushMediametrics() {
ALOGV("flushMediametrics");
@@ -1723,7 +1754,14 @@
if (mMetricsToUpload && mediametrics_count(mMetricsHandle) > 0) {
mediametrics_selfRecord(mMetricsHandle);
}
- mediametrics_delete(mMetricsHandle);
+ // keep previous metrics handle for subsequent getMetrics() calls.
+ // NOTE: There could be multiple error events, each flushing the metrics.
+ // We keep the last non-empty metrics handle, so getMetrics() in the
+ // next call will get the latest metrics prior to the errors.
+ if (mLastMetricsHandle != 0) {
+ mediametrics_delete(mLastMetricsHandle);
+ }
+ mLastMetricsHandle = mMetricsHandle;
mMetricsHandle = 0;
}
// we no longer have anything pending upload
@@ -1888,7 +1926,10 @@
});
}
- if (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder)) {
+ // NOTE: these were erroneously restricted to video encoders, but we want them for all
+ // codecs.
+ if (android::media::codec::provider_->subsession_metrics()
+ || (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder))) {
mBytesInput += buffer->size();
mFramesInput++;
}
@@ -1910,12 +1951,15 @@
++mInputBufferCounter;
}
-// when we get a buffer back from the codec
+// when we get a buffer back from the codec, always called from the looper thread
void MediaCodec::statsBufferReceived(int64_t presentationUs, const sp<MediaCodecBuffer> &buffer) {
CHECK_NE(mState, UNINITIALIZED);
- if (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder)) {
+ // NOTE: these were erroneously restricted to video encoders, but we want them for all
+ // codecs.
+ if (android::media::codec::provider_->subsession_metrics()
+ || (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder))) {
int32_t flags = 0;
(void) buffer->meta()->findInt32("flags", &flags);
@@ -2525,6 +2569,31 @@
return err;
}
+status_t MediaCodec::getRequiredResources(std::vector<InstanceResourceInfo>& resources) {
+ resources.clear();
+ // Make sure codec availability feature is on.
+ if (!android::media::codec::codec_availability()) {
+ return ERROR_UNSUPPORTED;
+ }
+ // Make sure that the codec was configured already.
+ if (mState != CONFIGURED && mState != STARTING && mState != STARTED &&
+ mState != FLUSHING && mState != FLUSHED) {
+ ALOGE("Codec wasn't configured yet!");
+ return INVALID_OPERATION;
+ }
+
+ if (!mRequiredResourceInfo.empty()) {
+ resources = mRequiredResourceInfo;
+ return OK;
+ }
+
+ // TODO: For now this is just an empty function.
+ // The actual implementation should use component interface
+ // (for example, through mCodec->getRequiredDeviceResources) to query the
+ // the required resources for this configuration, and fill in resources with the same.
+ return ERROR_UNSUPPORTED;
+}
+
// Media Format Shaping support
//
@@ -3613,6 +3682,10 @@
updateMediametrics();
results = mediametrics_dup(mMetricsHandle);
updateEphemeralMediametrics(results);
+ } else if (mLastMetricsHandle != 0) {
+ // After error, mMetricsHandle is cleared, but we keep the last
+ // metrics around so that it can be queried by getMetrics().
+ results = mediametrics_dup(mLastMetricsHandle);
} else {
results = mediametrics_dup(mMetricsHandle);
}
@@ -3882,6 +3955,7 @@
return true;
}
+// always called from the looper thread
MediaCodec::DequeueOutputResult MediaCodec::handleDequeueOutputBuffer(
const sp<AReplyToken> &replyID, bool newRequest) {
if (!isExecuting()) {
@@ -3937,6 +4011,9 @@
response->setInt32("flags", flags);
+ // NOTE: we must account the stats for an output buffer only after we
+ // already handled a potential output format change that could have
+ // started a new subsession.
statsBufferReceived(timeUs, buffer);
response->postReply(replyID);
@@ -5841,6 +5918,7 @@
}
}
+// always called from the looper thread
void MediaCodec::handleOutputFormatChangeIfNeeded(const sp<MediaCodecBuffer> &buffer) {
sp<AMessage> format = buffer->format();
if (mOutputFormat == format) {
@@ -5924,6 +6002,24 @@
}
}
}
+
+ // Update the width and the height.
+ int32_t left = 0, top = 0, right = 0, bottom = 0, width = 0, height = 0;
+ bool newSubsession = false;
+ if (android::media::codec::provider_->subsession_metrics()
+ && mOutputFormat->findInt32("width", &width)
+ && mOutputFormat->findInt32("height", &height)
+ && (width != mWidth || height != mHeight)) {
+ // consider a new subsession if the width or height changes.
+ newSubsession = true;
+ }
+ // TODO: properly detect new audio subsession
+
+ // Only consider a new subsession if we already have output (from a previous subsession).
+ if (newSubsession && mMetricsToUpload && mBytesEncoded > 0) {
+ handleStartingANewSubsession();
+ }
+
if (mFlags & kFlagIsAsync) {
onOutputFormatChanged();
} else {
@@ -5931,8 +6027,6 @@
postActivityNotificationIfPossible();
}
- // Update the width and the height.
- int32_t left = 0, top = 0, right = 0, bottom = 0, width = 0, height = 0;
bool resolutionChanged = false;
if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
mWidth = right - left + 1;
@@ -5959,6 +6053,35 @@
updateHdrMetrics(false /* isConfig */);
}
+// always called from the looper thread (and therefore not mutexed)
+void MediaCodec::handleStartingANewSubsession() {
+ // create a new metrics item for the subsession with the new resolution.
+ // TODO: properly account input counts for the previous and the new
+ // subsessions. We only find out that a new subsession started from the
+ // output format, but by that time we already accounted the input counts
+ // to the previous subsession.
+ flushMediametrics(); // this deletes mMetricsHandle, but stores it in mLastMetricsHandle
+
+ // hence mLastMetricsHandle has the metrics item for the previous subsession.
+ if ((mFlags & kFlagIsAsync) && mCallback != nullptr) {
+ sp<AMessage> msg = mCallback->dup();
+ msg->setInt32("callbackID", CB_METRICS_FLUSHED);
+ std::unique_ptr<mediametrics::Item> flushedMetrics(
+ mediametrics::Item::convert(mediametrics_dup(mLastMetricsHandle)));
+ msg->setObject("metrics", new WrapperObject<std::unique_ptr<mediametrics::Item>>(
+ std::move(flushedMetrics)));
+ msg->post();
+ }
+
+ // reuse/continue old metrics item for the new subsession.
+ mMetricsHandle = mediametrics_dup(mLastMetricsHandle);
+ mMetricsToUpload = true;
+ // TODO: configured width/height for the new subsession should be the
+ // previous width/height.
+ mSubsessionCount++;
+ resetSubsessionMetricsFields();
+}
+
void MediaCodec::extractCSD(const sp<AMessage> &format) {
mCSD.clear();
@@ -6959,6 +7082,18 @@
}
}
+void MediaCodec::onRequiredResourcesChanged(
+ const std::vector<InstanceResourceInfo>& resourceInfo) {
+ mRequiredResourceInfo = resourceInfo;
+ // Make sure codec availability feature is on.
+ if (mCallback != nullptr && android::media::codec::codec_availability()) {
+ // Post the callback
+ sp<AMessage> msg = mCallback->dup();
+ msg->setInt32("callbackID", CB_REQUIRED_RESOURCES_CHANGED);
+ msg->post();
+ }
+}
+
void MediaCodec::postActivityNotificationIfPossible() {
if (mActivityNotify == NULL) {
return;
diff --git a/media/libstagefright/data/media_codecs_google_c2_video.xml b/media/libstagefright/data/media_codecs_google_c2_video.xml
index fc0a5e9..72a2551 100644
--- a/media/libstagefright/data/media_codecs_google_c2_video.xml
+++ b/media/libstagefright/data/media_codecs_google_c2_video.xml
@@ -95,7 +95,7 @@
<Feature name="adaptive-playback" />
<Attribute name="software-codec" />
</MediaCodec>
- <MediaCodec name="c2.android.apv.decoder" type="video/apv">
+ <MediaCodec name="c2.android.apv.decoder" type="video/apv" enabled="false" minsdk="36" variant="!slow-cpu">
<Limit name="size" min="16x16" max="1920x1920"/>
<Limit name="alignment" value="2x2"/>
<Limit name="bitrate" range="1-240000000"/>
@@ -168,7 +168,7 @@
<Limit name="bitrate" range="1-40000000" />
<Feature name="bitrate-modes" value="VBR,CBR" />
</MediaCodec>
- <MediaCodec name="c2.android.apv.encoder" type="video/apv">
+ <MediaCodec name="c2.android.apv.encoder" type="video/apv" enabled="false" minsdk="36" variant="!slow-cpu">
<Limit name="size" min="2x2" max="1920x1920" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index 61b7198..4601831 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -255,7 +255,7 @@
<Feature name="adaptive-playback" />
<Attribute name="software-codec" />
</MediaCodec>
- <MediaCodec name="c2.android.apv.decoder" type="video/apv">
+ <MediaCodec name="c2.android.apv.decoder" type="video/apv" enabled="false" minsdk="36" variant="!slow-cpu">
<Limit name="size" min="16x16" max="1920x1920"/>
<Limit name="alignment" value="2x2"/>
<Limit name="bitrate" range="1-240000000"/>
@@ -417,7 +417,7 @@
<Feature name="qp-bounds" />
<Attribute name="software-codec" />
</MediaCodec>
- <MediaCodec name="c2.android.apv.encoder" type="video/apv" variant="!slow-cpu">
+ <MediaCodec name="c2.android.apv.encoder" type="video/apv" enabled="false" minsdk="36" variant="!slow-cpu">
<Limit name="size" min="2x2" max="1920x1920" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index b4794f1..df1ebd7 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -130,6 +130,11 @@
* Object at the "metrics" key.
*/
CB_METRICS_FLUSHED = 8,
+
+ /** Callback ID to notify the change in resource requirement
+ * for the codec component.
+ */
+ CB_REQUIRED_RESOURCES_CHANGED = 9,
};
static const pid_t kNoPid = -1;
@@ -149,6 +154,73 @@
static sp<PersistentSurface> CreatePersistentInputSurface();
+ /**
+ * Abstraction for the Global Codec resources.
+ * This encapsulates all the available codec resources on the device.
+ */
+ struct GlobalResourceInfo {
+ /**
+ * Name of the Resource type.
+ */
+ std::string mName;
+ /**
+ * Total count/capacity of resources of this type.
+ */
+ int mCapacity;
+ /**
+ * Available count of this resource type.
+ */
+ int mAvailable;
+
+ GlobalResourceInfo(const std::string& name, int capacity, int available) :
+ mName(name),
+ mCapacity(capacity),
+ mAvailable(available) {}
+
+ GlobalResourceInfo(const GlobalResourceInfo& info) :
+ mName(info.mName),
+ mCapacity(info.mCapacity),
+ mAvailable(info.mAvailable) {}
+ };
+
+ /**
+ * Abstraction for the resources associated with a codec instance.
+ * This encapsulates the required codec resources for a configured codec instance.
+ */
+ struct InstanceResourceInfo {
+ /**
+ * Name of the Resource type.
+ */
+ std::string mName;
+ /**
+ * Required resource count of this type.
+ */
+ int mStaticCount;
+ /**
+ * Per frame resource requirement of this resource type.
+ */
+ int mPerFrameCount;
+
+ InstanceResourceInfo(const std::string& name, int staticCount, int perFrameCount) :
+ mName(name),
+ mStaticCount(staticCount),
+ mPerFrameCount(perFrameCount) {}
+
+ InstanceResourceInfo(const InstanceResourceInfo& info) :
+ mName(info.mName),
+ mStaticCount(info.mStaticCount),
+ mPerFrameCount(info.mPerFrameCount) {}
+ };
+
+ /**
+ * Get a list of Globally available device codec resources.
+ *
+ * It will return INVALID_OPERATION if:
+ * - HAL does not implement codec availability API
+ * - codec_availability feature flag isn't defined.
+ */
+ static status_t getGloballyAvailableResources(std::vector<GlobalResourceInfo>& resources);
+
status_t configure(
const sp<AMessage> &format,
const sp<Surface> &nativeWindow,
@@ -162,6 +234,19 @@
const sp<IDescrambler> &descrambler,
uint32_t flags);
+ /**
+ * Get a list of required codec resources.
+ *
+ * This may only be called after configuring the codec.
+ *
+ * Calling this while the codec wasn't configured, will result in
+ * returning INVALID_OPERATION error code.
+ * It will also return INVALID_OPERATION if:
+ * - HAL does not implement codec availability API
+ * - codec_availability feature flag isn't defined.
+ */
+ status_t getRequiredResources(std::vector<InstanceResourceInfo>& resources);
+
status_t releaseCrypto();
status_t setCallback(const sp<AMessage> &callback);
@@ -491,12 +576,21 @@
Mutex mMetricsLock;
mediametrics_handle_t mMetricsHandle = 0;
+ mediametrics_handle_t mLastMetricsHandle = 0; // only accessed from the looper or destructor
bool mMetricsToUpload = false;
nsecs_t mLifetimeStartNs = 0;
void initMediametrics();
void updateMediametrics();
void flushMediametrics();
void resetMetricsFields();
+
+ // Reset the metrics fields for a new subsession.
+ void resetSubsessionMetricsFields();
+
+ // Start a new subsession (for metrics). This includes flushing the current
+ // metrics, notifying the client and resetting the session fields.
+ void handleStartingANewSubsession();
+
void updateEphemeralMediametrics(mediametrics_handle_t item);
void updateLowLatency(const sp<AMessage> &msg);
void updateCodecImportance(const sp<AMessage>& msg);
@@ -558,6 +652,7 @@
int32_t setOutputSurfaceCount;
int32_t resolutionChangeCount;
} mReliabilityContextMetrics;
+ int32_t mSubsessionCount;
// initial create parameters
AString mInitName;
@@ -678,6 +773,7 @@
void onCryptoError(const sp<AMessage> &msg);
void onError(status_t err, int32_t actionCode, const char *detail = NULL);
void onOutputFormatChanged();
+ void onRequiredResourcesChanged(const std::vector<InstanceResourceInfo>& resourceInfo);
status_t onSetParameters(const sp<AMessage> ¶ms);
@@ -777,6 +873,8 @@
friend class MediaTestHelper;
CodecErrorLog mErrorLog;
+ // Required resource info for this codec.
+ std::vector<InstanceResourceInfo> mRequiredResourceInfo;
DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
};
diff --git a/media/module/extractors/mpeg2/Android.bp b/media/module/extractors/mpeg2/Android.bp
index aa59a0c..63dbcda 100644
--- a/media/module/extractors/mpeg2/Android.bp
+++ b/media/module/extractors/mpeg2/Android.bp
@@ -44,7 +44,6 @@
shared_libs: [
"libbase",
- "libcgrouprc#29",
],
header_libs: [
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 867561a..5fbe48c 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1327,7 +1327,8 @@
// states to reset position info for pcm tracks
if (audio_is_linear_pcm(mFormat)
- && (state == IDLE || state == STOPPED || state == FLUSHED)) {
+ && (state == IDLE || state == STOPPED || state == FLUSHED
+ || state == PAUSED)) {
mFrameMap.reset();
if (!isFastTrack()) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 6f47e91..04ebb57 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -8767,6 +8767,7 @@
case AUDIO_USAGE_SAFETY:
case AUDIO_USAGE_VEHICLE_STATUS:
case AUDIO_USAGE_ANNOUNCEMENT:
+ case AUDIO_USAGE_SPEAKER_CLEANUP:
break;
default:
return false;
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index c37540c..f8f91fc 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -753,7 +753,7 @@
TEST_P(AudioPolicyManagerTestMsd, GetDirectProfilesForAttributesWithMsd) {
const audio_attributes_t attr = {
AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
- AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+ AUDIO_SOURCE_INVALID, AUDIO_FLAG_NONE, ""};
// count expected direct profiles for the default device
int countDirectProfilesPrimary = 0;
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 3f2a617..b9c8206 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -101,8 +101,8 @@
"android.frameworks.cameraservice.device@2.0",
"android.frameworks.cameraservice.device@2.1",
"android.frameworks.cameraservice.common-V1-ndk",
- "android.frameworks.cameraservice.service-V2-ndk",
- "android.frameworks.cameraservice.device-V2-ndk",
+ "android.frameworks.cameraservice.service-V3-ndk",
+ "android.frameworks.cameraservice.device-V3-ndk",
"android.hardware.camera.common-V1-ndk",
"android.hardware.camera.device-V3-ndk",
"android.hardware.camera.metadata-V3-ndk",
@@ -179,6 +179,7 @@
"device3/aidl/AidlCamera3Device.cpp",
"device3/aidl/AidlCamera3OutputUtils.cpp",
"device3/aidl/AidlCamera3OfflineSession.cpp",
+ "device3/aidl/AidlCamera3SharedDevice.cpp",
"gui/RingBufferConsumer.cpp",
"hidl/AidlCameraDeviceCallbacks.cpp",
"hidl/AidlCameraServiceListener.cpp",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 8d44e06..df94478 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -564,7 +564,7 @@
updateStatus(StatusInternal::NOT_PRESENT, cameraId);
mVirtualDeviceCameraIdMapper.removeCamera(cameraId);
- sp<BasicClient> clientToDisconnectOnline, clientToDisconnectOffline;
+ std::vector<sp<BasicClient>> clientsToDisconnectOnline, clientsToDisconnectOffline;
{
// Don't do this in updateStatus to avoid deadlock over mServiceLock
Mutex::Autolock lock(mServiceLock);
@@ -574,12 +574,12 @@
// Remove online as well as offline client from the list of active clients,
// if they are present
- clientToDisconnectOnline = removeClientLocked(cameraId);
- clientToDisconnectOffline = removeClientLocked(kOfflineDevice + cameraId);
+ clientsToDisconnectOnline = removeClientsLocked(cameraId);
+ clientsToDisconnectOffline = removeClientsLocked(kOfflineDevice + cameraId);
}
- disconnectClient(cameraId, clientToDisconnectOnline);
- disconnectClient(kOfflineDevice + cameraId, clientToDisconnectOffline);
+ disconnectClients(cameraId, clientsToDisconnectOnline);
+ disconnectClients(kOfflineDevice + cameraId, clientsToDisconnectOffline);
removeStates(cameraId);
} else {
@@ -653,6 +653,13 @@
}
}
+void CameraService::disconnectClients(const std::string& id,
+ std::vector<sp<BasicClient>> clientsToDisconnect) {
+ for (auto& client : clientsToDisconnect) {
+ disconnectClient(id, client);
+ }
+}
+
void CameraService::disconnectClient(const std::string& id, sp<BasicClient> clientToDisconnect) {
if (clientToDisconnect.get() != nullptr) {
ALOGI("%s: Client for camera ID %s evicted due to device status change from HAL",
@@ -1484,8 +1491,8 @@
const std::string& cameraId, int api1CameraId, int facing, int sensorOrientation,
int servicePid, std::pair<int, IPCTransport> deviceVersionAndTransport,
apiLevel effectiveApiLevel, bool overrideForPerfClass, int rotationOverride,
- bool forceSlowJpegMode, const std::string& originalCameraId,
- /*out*/ sp<BasicClient>* client) {
+ bool forceSlowJpegMode, const std::string& originalCameraId, bool sharedMode,
+ /*out*/sp<BasicClient>* client) {
// For HIDL devices
if (deviceVersionAndTransport.second == IPCTransport::HIDL) {
// Create CameraClient based on device version reported by the HAL.
@@ -1520,7 +1527,7 @@
cameraService->mAttributionAndPermissionUtils,
clientAttribution, callingPid, cameraId, api1CameraId, facing,
sensorOrientation, servicePid, overrideForPerfClass,
- rotationOverride, forceSlowJpegMode);
+ rotationOverride, forceSlowJpegMode, /*sharedMode*/false);
ALOGI("%s: Camera1 API (legacy), rotationOverride %d, forceSlowJpegMode %d",
__FUNCTION__, rotationOverride, forceSlowJpegMode);
} else { // Camera2 API route
@@ -1530,7 +1537,7 @@
cameraService, tmp, cameraService->mCameraServiceProxyWrapper,
cameraService->mAttributionAndPermissionUtils, clientAttribution, callingPid,
systemNativeClient, cameraId, facing, sensorOrientation, servicePid,
- overrideForPerfClass, rotationOverride, originalCameraId);
+ overrideForPerfClass, rotationOverride, originalCameraId, sharedMode);
ALOGI("%s: Camera2 API, rotationOverride %d", __FUNCTION__, rotationOverride);
}
return Status::ok();
@@ -1630,7 +1637,8 @@
/*targetSdkVersion*/ __ANDROID_API_FUTURE__,
/*rotationOverride*/
hardware::ICameraService::ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT,
- /*forceSlowJpegMode*/ false, cameraIdStr, /*isNonSystemNdk*/ false, /*out*/ tmp))
+ /*forceSlowJpegMode*/ false, cameraIdStr, /*isNonSystemNdk*/ false,
+ /*sharedMode*/false, /*out*/ tmp))
.isOk()) {
ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().c_str());
}
@@ -1700,11 +1708,12 @@
}
Status CameraService::validateConnectLocked(const std::string& cameraId,
- const AttributionSourceState& clientAttribution) const {
+ const AttributionSourceState& clientAttribution,
+ bool sharedMode) const {
#ifdef __BRILLO__
UNUSED(clientAttribution);
#else
- Status allowed = validateClientPermissionsLocked(cameraId, clientAttribution);
+ Status allowed = validateClientPermissionsLocked(cameraId, clientAttribution, sharedMode);
if (!allowed.isOk()) {
return allowed;
}
@@ -1742,7 +1751,8 @@
}
Status CameraService::validateClientPermissionsLocked(
- const std::string& cameraId, const AttributionSourceState& clientAttribution) const {
+ const std::string& cameraId, const AttributionSourceState& clientAttribution,
+ bool sharedMode) const {
int callingPid = getCallingPid();
int callingUid = getCallingUid();
@@ -1763,6 +1773,14 @@
"found while trying to query device kind", cameraId.c_str());
}
+ if (flags::camera_multi_client() && sharedMode
+ && (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA)) {
+ ALOGE("%s: camera id %s is not system camera. Device sharing only supported for"
+ " system cameras.", __FUNCTION__, cameraId.c_str());
+ return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "camera device sharing not supported for "
+ "camera ID \"%s\"", cameraId.c_str());
+ }
+
// Get the device id that owns this camera.
auto [deviceId, _] = mVirtualDeviceCameraIdMapper.getDeviceIdAndMappedCameraIdPair(cameraId);
AttributionSourceState clientAttributionWithDeviceId = clientAttribution;
@@ -1886,6 +1904,28 @@
__FUNCTION__);
}
+ if (flags::camera_multi_client()) {
+ sp<BasicClient> clientSp = clientDescriptor->getValue();
+ auto primaryClient = mActiveClientManager.getPrimaryClient(desc->getKey());
+ if (primaryClient == nullptr) {
+ // There is no primary client yet. Assign this first client as
+ // primary
+ clientSp->setPrimaryClient(true);
+ } else {
+ // There is already primary client. If the incoming client has a
+ // higher priority than the existing primary, then assign incoming
+ // client as primary and change the existing client to secondary.
+ // Otherwise incoming client is secondary client.
+ if (clientDescriptor->getPriority() <= primaryClient->getPriority()) {
+ clientSp->setPrimaryClient(true);
+ primaryClient->getValue()->setPrimaryClient(false);
+ primaryClient->getValue()->notifyClientSharedAccessPriorityChanged(false);
+ } else {
+ clientSp->setPrimaryClient(false);
+ }
+ }
+ }
+
// And register a death notification for the client callback. Do
// this last to avoid Binder policy where a nested Binder
// transaction might be pre-empted to service the client death
@@ -1900,6 +1940,7 @@
status_t CameraService::handleEvictionsLocked(const std::string& cameraId, int clientPid,
apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback,
const std::string& packageName, int oomScoreOffset, bool systemNativeClient,
+ bool sharedMode,
/*out*/
sp<BasicClient>* client,
std::shared_ptr<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>>* partial) {
@@ -1951,7 +1992,8 @@
clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
state->getConflicting(), resource_policy::NATIVE_ADJ, clientPid,
- ActivityManager::PROCESS_STATE_BOUND_TOP, oomScoreOffset, systemNativeClient);
+ ActivityManager::PROCESS_STATE_BOUND_TOP, oomScoreOffset, systemNativeClient,
+ sharedMode);
} else {
// Get current active client PIDs
std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
@@ -1987,7 +2029,7 @@
clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
state->getConflicting(), actualScore, clientPid, actualState,
- oomScoreOffset, systemNativeClient);
+ oomScoreOffset, systemNativeClient, sharedMode);
}
resource_policy::ClientPriority clientPriority = clientDescriptor->getPriority();
@@ -2160,7 +2202,7 @@
cameraClient, cameraIdStr, api1CameraId, resolvedClientAttribution,
/*systemNativeClient*/ false, API_1,
/*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion, rotationOverride,
- forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*out*/ client);
+ forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*sharedMode*/false, /*out*/ client);
if (!ret.isOk()) {
logRejected(cameraIdStr, getCallingPid(),
@@ -2244,8 +2286,7 @@
const std::string& unresolvedCameraId,
int oomScoreOffset, int targetSdkVersion,
int rotationOverride, const AttributionSourceState& clientAttribution, int32_t devicePolicy,
- /*out*/
- sp<hardware::camera2::ICameraDeviceUser>* device) {
+ bool sharedMode, /*out*/sp<hardware::camera2::ICameraDeviceUser>* device) {
ATRACE_CALL();
RunThreadWithRealtimePriority priorityBump;
Status ret = Status::ok();
@@ -2325,7 +2366,8 @@
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks, CameraDeviceClient>(
cameraCb, cameraId, /*api1CameraId*/ -1, resolvedClientAttribution, systemNativeClient,
API_2, /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, rotationOverride,
- /*forceSlowJpegMode*/ false, unresolvedCameraId, isNonSystemNdk, /*out*/ client);
+ /*forceSlowJpegMode*/ false, unresolvedCameraId, isNonSystemNdk, sharedMode,
+ /*out*/ client);
if (!ret.isOk()) {
logRejected(cameraId, clientPid, clientPackageName, toStdString(ret.toString8()));
@@ -2405,7 +2447,7 @@
bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
int rotationOverride, bool forceSlowJpegMode,
const std::string& originalCameraId, bool isNonSystemNdk,
- /*out*/ sp<CLIENT>& device) {
+ bool sharedMode, /*out*/ sp<CLIENT>& device) {
binder::Status ret = binder::Status::ok();
nsecs_t openTimeNs = systemTime();
@@ -2432,7 +2474,7 @@
}
// Enforce client permissions and do basic validity checks
- if (!(ret = validateConnectLocked(cameraId, clientAttribution)).isOk()) {
+ if (!(ret = validateConnectLocked(cameraId, clientAttribution, sharedMode)).isOk()) {
return ret;
}
@@ -2453,7 +2495,7 @@
cameraId, clientAttribution.pid, effectiveApiLevel,
IInterface::asBinder(cameraCb),
clientAttribution.packageName.value_or(kUnknownPackageName), oomScoreOffset,
- systemNativeClient, /*out*/ &clientTmp,
+ systemNativeClient, sharedMode, /*out*/ &clientTmp,
/*out*/ &partial)) != NO_ERROR) {
switch (err) {
case -ENODEV:
@@ -2504,7 +2546,7 @@
systemNativeClient, cameraId, api1CameraId, facing, orientation,
getpid(), deviceVersionAndTransport, effectiveApiLevel,
overrideForPerfClass, rotationOverride, forceSlowJpegMode,
- originalCameraId,
+ originalCameraId, sharedMode,
/*out*/ &tmp))
.isOk()) {
return ret;
@@ -2753,7 +2795,7 @@
/*conflictingKeys*/ std::set<std::string>(), onlinePriority.getScore(),
onlineClientDesc->getOwnerId(), onlinePriority.getState(),
// native clients don't have offline processing support.
- /*ommScoreOffset*/ 0, /*systemNativeClient*/false);
+ /*ommScoreOffset*/ 0, /*systemNativeClient*/false, /*sharedMode*/false);
if (offlineClientDesc == nullptr) {
ALOGE("%s: Offline client descriptor was NULL", __FUNCTION__);
return BAD_VALUE;
@@ -3686,6 +3728,25 @@
updateAudioRestrictionLocked();
}
+bool CameraService::isOnlyClient(const BasicClient* client) {
+ Mutex::Autolock lock(mServiceLock);
+ bool ret = true;
+ if (!flags::camera_multi_client()) {
+ return ret;
+ }
+ if (client != nullptr) {
+ std::string camId = client->mCameraIdStr;
+ for (const auto& i : mActiveClientManager.getAll()) {
+ auto clientSp = i->getValue();
+ auto curCamId = i->getKey();
+ if (!curCamId.compare(camId) && clientSp.get() != client) {
+ return false;
+ }
+ }
+ }
+ return ret;
+}
+
bool CameraService::evictClientIdByRemote(const wp<IBinder>& remote) {
bool ret = false;
{
@@ -3746,20 +3807,20 @@
return state;
}
-sp<CameraService::BasicClient> CameraService::removeClientLocked(const std::string& cameraId) {
+std::vector<sp<CameraService::BasicClient>> CameraService::removeClientsLocked(
+ const std::string& cameraId) {
// Remove from active clients list
- auto clientDescriptorPtr = mActiveClientManager.remove(cameraId);
- if (clientDescriptorPtr == nullptr) {
- ALOGW("%s: Could not evict client, no client for camera ID %s", __FUNCTION__,
- cameraId.c_str());
- return sp<BasicClient>{nullptr};
+ std::vector<sp<CameraService::BasicClient>> clients;
+ std::vector<CameraService::DescriptorPtr> clientDescriptors;
+ clientDescriptors = mActiveClientManager.removeAll(cameraId);
+ for (const auto& clientDescriptorPtr : clientDescriptors) {
+ sp<BasicClient> client = clientDescriptorPtr->getValue();
+ if (client.get() != nullptr) {
+ cacheClientTagDumpIfNeeded(clientDescriptorPtr->getKey(), client.get());
+ }
+ clients.push_back(client);
}
-
- sp<BasicClient> client = clientDescriptorPtr->getValue();
- if (client.get() != nullptr) {
- cacheClientTagDumpIfNeeded(clientDescriptorPtr->getKey(), client.get());
- }
- return client;
+ return clients;
}
void CameraService::doUserSwitch(const std::vector<int32_t>& newUserIds) {
@@ -4043,11 +4104,11 @@
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const AttributionSourceState& clientAttribution, int callingPid, bool systemNativeClient,
const std::string& cameraIdStr, int api1CameraId, int cameraFacing, int sensorOrientation,
- int servicePid, int rotationOverride)
+ int servicePid, int rotationOverride, bool sharedMode)
: CameraService::BasicClient(cameraService, IInterface::asBinder(cameraClient),
attributionAndPermissionUtils, clientAttribution, callingPid,
systemNativeClient, cameraIdStr, cameraFacing, sensorOrientation,
- servicePid, rotationOverride),
+ servicePid, rotationOverride, sharedMode),
mCameraId(api1CameraId) {
LOG1("Client::Client E (pid %d, id %d)", callingPid, mCameraId);
@@ -4075,7 +4136,7 @@
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const AttributionSourceState& clientAttribution, int callingPid, bool nativeClient,
const std::string& cameraIdStr, int cameraFacing, int sensorOrientation, int servicePid,
- int rotationOverride)
+ int rotationOverride, bool sharedMode)
: AttributionAndPermissionUtilsEncapsulator(attributionAndPermissionUtils),
mDestructionStarted(false),
mCameraIdStr(cameraIdStr),
@@ -4087,7 +4148,7 @@
mServicePid(servicePid),
mDisconnected(false),
mUidIsTrusted(false),
- mRotationOverride(rotationOverride),
+ mRotationOverride(rotationOverride), mSharedMode(sharedMode),
mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE),
mRemoteBinder(remoteCallback),
mCameraOpen(false),
@@ -4128,8 +4189,15 @@
sCameraService->removeByClient(this);
sCameraService->logDisconnected(mCameraIdStr, mCallingPid, getPackageName());
- sCameraService->mCameraProviderManager->removeRef(CameraProviderManager::DeviceMode::CAMERA,
- mCameraIdStr);
+ if (!flags::camera_multi_client() || !mSharedMode || (mSharedMode &&
+ sCameraService->isOnlyClient(this))) {
+ // Remove the HAL reference for the camera in either of the following scenarios :
+ // 1) Camera was opened in non-shared mode.
+ // 2) Camera was opened in shared mode and this is the last client using
+ // the camera which is being disconnected
+ sCameraService->mCameraProviderManager->removeRef(CameraProviderManager::DeviceMode::CAMERA,
+ mCameraIdStr);
+ }
sp<IBinder> remote = getRemote();
if (remote != nullptr) {
@@ -4137,8 +4205,11 @@
}
notifyCameraClosing();
- // Notify flashlight that a camera device is closed.
- sCameraService->mFlashlight->deviceClosed(mCameraIdStr);
+ if (!flags::camera_multi_client() || !mSharedMode || (mSharedMode &&
+ sCameraService->isOnlyClient(this))) {
+ // Notify flashlight that a camera device is closed.
+ sCameraService->mFlashlight->deviceClosed(mCameraIdStr);
+ }
ALOGI("%s: Disconnected client for camera %s for PID %d", __FUNCTION__, mCameraIdStr.c_str(),
mCallingPid);
@@ -4315,7 +4386,8 @@
sCameraService->mUidPolicy->registerMonitorUid(getClientUid(), /*openCamera*/ true);
// Notify listeners of camera open/close status
- sCameraService->updateOpenCloseStatus(mCameraIdStr, true /*open*/, getPackageName());
+ sCameraService->updateOpenCloseStatus(mCameraIdStr, true /*open*/, getPackageName(),
+ mSharedMode);
return OK;
}
@@ -4453,8 +4525,11 @@
StatusInternal::ENUMERATING, StatusInternal::NOT_PRESENT};
// Transition to PRESENT if the camera is not in either of the rejected states
- sCameraService->updateStatus(StatusInternal::PRESENT,
- mCameraIdStr, rejected);
+ if (!flags::camera_multi_client() || !mSharedMode || (mSharedMode
+ && sCameraService->isOnlyClient(this))) {
+ sCameraService->updateStatus(StatusInternal::PRESENT,
+ mCameraIdStr, rejected);
+ }
}
// When using the data delivery permission checks, the open state does not involve AppOps
@@ -4469,11 +4544,23 @@
sCameraService->mUidPolicy->unregisterMonitorUid(getClientUid(), /*closeCamera*/ true);
// Notify listeners of camera open/close status
- sCameraService->updateOpenCloseStatus(mCameraIdStr, false /*open*/, getPackageName());
+ sCameraService->updateOpenCloseStatus(mCameraIdStr, false /*open*/, getPackageName(),
+ mSharedMode);
return OK;
}
+int32_t CameraService::getUidProcessState(int32_t uid) {
+ const auto& activityManager = getActivityManager();
+ int32_t procState = ActivityManager::PROCESS_STATE_NONEXISTENT;
+ if (activityManager != nullptr) {
+ procState = activityManager->getUidProcessState(uid, toString16(kServiceName));
+ } else {
+ ALOGE("%s: getActivityManager returned nullptr.", __FUNCTION__);
+ }
+ return procState;
+}
+
void CameraService::BasicClient::opChanged(int32_t op, const String16&) {
ATRACE_CALL();
if (mAppOpsManager == nullptr) {
@@ -4530,12 +4617,9 @@
[&](const auto& attr) {
uid = static_cast<uid_t>(attr.uid);
});
- const auto& activityManager = getActivityManager();
- if (activityManager != nullptr) {
- procState = activityManager->getUidProcessState(uid, toString16(kServiceName));
- } else {
- ALOGD("%s: getActivityManager returned nullptr.", __FUNCTION__);
- }
+ procState = getUidProcessState(uid);
+ } else if (flags::query_process_state()) {
+ procState = getUidProcessState(getClientUid());
} else {
procState = sCameraService->mUidPolicy->getProcState(getClientUid());
}
@@ -4580,6 +4664,35 @@
disconnect();
}
+status_t CameraService::BasicClient::isPrimaryClient(bool* isPrimary) {
+ ATRACE_CALL();
+ if (!flags::camera_multi_client()) {
+ return INVALID_OPERATION;
+ }
+
+ if (!mSharedMode) {
+ ALOGW("%s: Invalid operation when camera is not opened in shared mode", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ *isPrimary = mIsPrimaryClient;
+ return OK;
+}
+
+status_t CameraService::BasicClient::setPrimaryClient(bool isPrimary) {
+ ATRACE_CALL();
+
+ if (!flags::camera_multi_client()) {
+ return INVALID_OPERATION;
+ }
+
+ if (!mSharedMode) {
+ ALOGW("%s:Invalid operation when camera is not opened in shared mode", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ mIsPrimaryClient = isPrimary;
+ return OK;
+}
+
// ----------------------------------------------------------------------------
void CameraService::Client::notifyError(int32_t errorCode,
@@ -5130,12 +5243,27 @@
void CameraService::CameraState::setClientPackage(const std::string& clientPackage) {
Mutex::Autolock lock(mStatusLock);
- mClientPackage = clientPackage;
+ mClientPackages.clear();
+ mClientPackages.insert(clientPackage);
}
std::string CameraService::CameraState::getClientPackage() const {
Mutex::Autolock lock(mStatusLock);
- return mClientPackage;
+ if (!mClientPackages.empty()) {
+ std::set<std::string>::iterator it = mClientPackages.begin();
+ return *it;
+ }
+ return std::string();
+}
+
+void CameraService::CameraState::addClientPackage(const std::string& clientPackage) {
+ Mutex::Autolock lock(mStatusLock);
+ mClientPackages.insert(clientPackage);
+}
+
+void CameraService::CameraState::removeClientPackage(const std::string& clientPackage) {
+ Mutex::Autolock lock(mStatusLock);
+ mClientPackages.erase(clientPackage);
}
// ----------------------------------------------------------------------------
@@ -5183,6 +5311,39 @@
return descriptor->getValue();
}
+void CameraService::CameraClientManager::remove(const CameraService::DescriptorPtr& value) {
+ ClientManager::remove(value);
+ if (!flags::camera_multi_client()) {
+ return;
+ }
+ auto clientToRemove = value->getValue();
+ if ((clientToRemove.get() != nullptr) && clientToRemove->mSharedMode) {
+ bool primaryClient = false;
+ status_t ret = clientToRemove->isPrimaryClient(&primaryClient);
+ if ((ret == OK) && primaryClient) {
+ // Primary client is being removed. Find the next higher priority
+ // client to become primary client.
+ auto clientDescriptor = get(value->getKey());
+ if (clientDescriptor == nullptr) {
+ ALOGV("CameraService::CameraClientManager::no other clients are using same camera");
+ return;
+ }
+ resource_policy::ClientPriority highestPriority = clientDescriptor->getPriority();
+ sp<BasicClient> highestPriorityClient = clientDescriptor->getValue();
+ if (highestPriorityClient.get() != nullptr) {
+ for (auto& i : getAll()) {
+ if ((i->getKey() == value->getKey()) && (i->getPriority() < highestPriority)) {
+ highestPriority = i->getPriority();
+ highestPriorityClient = i->getValue();
+ }
+ }
+ highestPriorityClient->setPrimaryClient(true);
+ highestPriorityClient->notifyClientSharedAccessPriorityChanged(true);
+ }
+ }
+ }
+}
+
std::string CameraService::CameraClientManager::toString() const {
auto all = getAll();
std::ostringstream ret;
@@ -5228,14 +5389,14 @@
CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
const std::string& key, const sp<BasicClient>& value, int32_t cost,
const std::set<std::string>& conflictingKeys, int32_t score, int32_t ownerId,
- int32_t state, int32_t oomScoreOffset, bool systemNativeClient) {
+ int32_t state, int32_t oomScoreOffset, bool systemNativeClient, bool sharedMode) {
int32_t score_adj = systemNativeClient ? kSystemNativeClientScore : score;
int32_t state_adj = systemNativeClient ? kSystemNativeClientState : state;
return std::make_shared<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>>(
key, value, cost, conflictingKeys, score_adj, ownerId, state_adj,
- systemNativeClient, oomScoreOffset);
+ systemNativeClient, oomScoreOffset, sharedMode);
}
CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
@@ -5244,7 +5405,7 @@
return makeClientDescriptor(partial->getKey(), value, partial->getCost(),
partial->getConflicting(), partial->getPriority().getScore(),
partial->getOwnerId(), partial->getPriority().getState(), oomScoreOffset,
- systemNativeClient);
+ systemNativeClient, partial->getSharedMode());
}
// ----------------------------------------------------------------------------
@@ -5776,7 +5937,7 @@
}
void CameraService::updateOpenCloseStatus(const std::string& cameraId, bool open,
- const std::string& clientPackageName) {
+ const std::string& clientPackageName, bool sharedMode) {
auto state = getCameraState(cameraId);
if (state == nullptr) {
ALOGW("%s: Could not update the status for %s, no such device exists", __FUNCTION__,
@@ -5784,9 +5945,17 @@
return;
}
if (open) {
- state->setClientPackage(clientPackageName);
+ if (flags::camera_multi_client() && sharedMode) {
+ state->addClientPackage(clientPackageName);
+ } else {
+ state->setClientPackage(clientPackageName);
+ }
} else {
- state->setClientPackage(std::string());
+ if (flags::camera_multi_client() && sharedMode) {
+ state->removeClientPackage(clientPackageName);
+ } else {
+ state->setClientPackage(std::string());
+ }
}
// Get the device id and app-visible camera id for the given HAL-visible camera id.
@@ -5805,7 +5974,10 @@
ret = it->getListener()->onCameraOpened(mappedCameraId, clientPackageName,
deviceId);
} else {
- ret = it->getListener()->onCameraClosed(mappedCameraId, deviceId);
+ if (!flags::camera_multi_client() || !sharedMode || (sharedMode &&
+ mActiveClientManager.getCameraClient(cameraId) == nullptr)) {
+ ret = it->getListener()->onCameraClosed(mappedCameraId, deviceId);
+ }
}
it->handleBinderStatus(ret,
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 4c93ae1..9c75ede 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -181,7 +181,7 @@
const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
const std::string& cameraId, int scoreOffset, int targetSdkVersion,
int rotationOverride, const AttributionSourceState& clientAttribution,
- int32_t devicePolicy,
+ int32_t devicePolicy, bool sharedMode,
/*out*/
sp<hardware::camera2::ICameraDeviceUser>* device);
@@ -384,6 +384,8 @@
virtual void notifyError(int32_t errorCode,
const CaptureResultExtras& resultExtras) = 0;
+ virtual void notifyClientSharedAccessPriorityChanged(bool primaryClient) = 0;
+
// Get the UID of the application client using this
virtual uid_t getClientUid() const;
@@ -453,12 +455,16 @@
virtual status_t injectSessionParams(
const hardware::camera2::impl::CameraMetadataNative& sessionParams) = 0;
+ status_t isPrimaryClient(/*out*/bool* isPrimary);
+
+ status_t setPrimaryClient(bool isPrimary);
+
protected:
BasicClient(const sp<CameraService>& cameraService, const sp<IBinder>& remoteCallback,
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const AttributionSourceState& clientAttribution, int callingPid,
bool nativeClient, const std::string& cameraIdStr, int cameraFacing,
- int sensorOrientation, int servicePid, int rotationOverride);
+ int sensorOrientation, int servicePid, int rotationOverride, bool sharedMode);
virtual ~BasicClient();
@@ -480,6 +486,8 @@
bool mDisconnected;
bool mUidIsTrusted;
int mRotationOverride;
+ bool mSharedMode;
+ bool mIsPrimaryClient;
mutable Mutex mAudioRestrictionLock;
int32_t mAudioRestriction;
@@ -562,7 +570,8 @@
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const AttributionSourceState& clientAttribution, int callingPid,
bool systemNativeClient, const std::string& cameraIdStr, int api1CameraId,
- int cameraFacing, int sensorOrientation, int servicePid, int rotationOverride);
+ int cameraFacing, int sensorOrientation, int servicePid, int rotationOverride,
+ bool sharedMode);
~Client();
// return our camera client
@@ -622,6 +631,8 @@
CameraClientManager();
virtual ~CameraClientManager();
+ virtual void remove(const DescriptorPtr& value) override;
+
/**
* Return a strong pointer to the active BasicClient for this camera ID, or an empty
* if none exists.
@@ -639,7 +650,8 @@
static DescriptorPtr makeClientDescriptor(const std::string& key,
const sp<BasicClient>& value, int32_t cost,
const std::set<std::string>& conflictingKeys, int32_t score,
- int32_t ownerId, int32_t state, int oomScoreOffset, bool systemNativeClient);
+ int32_t ownerId, int32_t state, int oomScoreOffset, bool systemNativeClient,
+ bool sharedMode);
/**
* Make a ClientDescriptor object wrapping the given BasicClient strong pointer with
@@ -654,6 +666,15 @@
int32_t updateAudioRestriction();
int32_t updateAudioRestrictionLocked();
+ /**
+ * Returns true if the given client is the only client in the active clients list for a given
+ * camera.
+ *
+ * This method acquires mServiceLock.
+ */
+ bool isOnlyClient(const BasicClient* client);
+
+
private:
// TODO: b/263304156 update this to make use of a death callback for more
@@ -670,6 +691,8 @@
return activityManager;
}
+ static int32_t getUidProcessState(int32_t uid);
+
/**
* Typesafe version of device status, containing both the HAL-layer and the service interface-
* layer values.
@@ -771,6 +794,10 @@
void setClientPackage(const std::string& clientPackage);
std::string getClientPackage() const;
+ void addClientPackage(const std::string& clientPackage);
+ void removeClientPackage(const std::string& clientPackage);
+ std::set<std::string> getClientPackages() const;
+
/**
* Return the unavailable physical ids for this device.
*
@@ -783,7 +810,7 @@
const int mCost;
std::set<std::string> mConflicting;
std::set<std::string> mUnavailablePhysicalIds;
- std::string mClientPackage;
+ std::set<std::string> mClientPackages;
mutable Mutex mStatusLock;
CameraParameters mShimParams;
const SystemCameraKind mSystemCameraKind;
@@ -913,9 +940,11 @@
// Check if we can connect, before we acquire the service lock.
binder::Status validateConnectLocked(const std::string& cameraId,
- const AttributionSourceState& clientAttribution) const;
+ const AttributionSourceState& clientAttribution,
+ bool sharedMode) const;
binder::Status validateClientPermissionsLocked(
- const std::string& cameraId, const AttributionSourceState& clientAttribution) const;
+ const std::string& cameraId, const AttributionSourceState& clientAttribution,
+ bool sharedMode) const;
void logConnectionAttempt(int clientPid, const std::string& clientPackageName,
const std::string& cameraId, apiLevel effectiveApiLevel) const;
@@ -927,7 +956,7 @@
// Only call with with mServiceLock held.
status_t handleEvictionsLocked(const std::string& cameraId, int clientPid,
apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback,
- const std::string& packageName, int scoreOffset, bool systemNativeClient,
+ const std::string& packageName, int scoreOffset, bool systemNativeClient, bool sharedMode,
/*out*/
sp<BasicClient>* client,
std::shared_ptr<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>>* partial);
@@ -964,7 +993,7 @@
bool shimUpdateOnly, int scoreOffset, int targetSdkVersion,
int rotationOverride, bool forceSlowJpegMode,
const std::string& originalCameraId, bool isNonSystemNdk,
- /*out*/ sp<CLIENT>& device);
+ bool sharedMode, /*out*/ sp<CLIENT>& device);
// Lock guarding camera service state
Mutex mServiceLock;
@@ -1072,12 +1101,12 @@
std::string cameraIdIntToStrLocked(int cameraIdInt, int32_t deviceId, int32_t devicePolicy);
/**
- * Remove a single client corresponding to the given camera id from the list of active clients.
+ * Remove all the clients corresponding to the given camera id from the list of active clients.
* If none exists, return an empty strongpointer.
*
* This method must be called with mServiceLock held.
*/
- sp<CameraService::BasicClient> removeClientLocked(const std::string& cameraId);
+ std::vector<sp<CameraService::BasicClient>> removeClientsLocked(const std::string& cameraId);
/**
* Handle a notification that the current device user has changed.
@@ -1285,7 +1314,7 @@
* This method acqiures mStatusListenerLock.
*/
void updateOpenCloseStatus(const std::string& cameraId, bool open,
- const std::string& packageName);
+ const std::string& packageName, bool sharedMode);
// flashlight control
sp<CameraFlashlight> mFlashlight;
@@ -1460,7 +1489,7 @@
std::pair<int, IPCTransport> deviceVersionAndIPCTransport,
apiLevel effectiveApiLevel, bool overrideForPerfClass,
int rotationOverride, bool forceSlowJpegMode,
- const std::string& originalCameraId,
+ const std::string& originalCameraId, bool sharedMode,
/*out*/ sp<BasicClient>* client);
static std::string toString(std::set<userid_t> intSet);
@@ -1476,6 +1505,9 @@
void disconnectClient(const std::string& id, sp<BasicClient> clientToDisconnect);
+ void disconnectClients(const std::string& id,
+ std::vector<sp<BasicClient>> clientsToDisconnect);
+
// Regular online and offline devices must not be in conflict at camera service layer.
// Use separate keys for offline devices.
static const std::string kOfflineDevice;
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp
index e648a36..70647b4 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp
@@ -79,6 +79,15 @@
return binder::Status::ok();
}
+binder::Status AidlCameraDeviceCallbacks::onClientSharedAccessPriorityChanged(bool primaryClient) {
+ if (!flags::camera_multi_client()) {
+ return binder::Status::ok();
+ }
+ auto ret = mBase->onClientSharedAccessPriorityChanged(primaryClient);
+ LOG_STATUS_ERROR_IF_NOT_OK(ret, "onClientSharedAccessPriorityChanged")
+ return binder::Status::ok();
+ }
+
binder::Status AidlCameraDeviceCallbacks::onDeviceIdle() {
auto ret = mBase->onDeviceIdle();
LOG_STATUS_ERROR_IF_NOT_OK(ret, "onDeviceIdle")
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h
index 5cff5b3..07bf7d8 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h
@@ -75,6 +75,8 @@
binder::Status onRequestQueueEmpty() override;
+ binder::Status onClientSharedAccessPriorityChanged(bool primaryClient) override;
+
status_t linkToDeath(const sp<DeathRecipient>& recipient, void* cookie,
uint32_t flags) override;
status_t unlinkToDeath(const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
index 9e6a925..fc987b2 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
@@ -192,6 +192,16 @@
return fromUStatus(ret);
}
+ndk::ScopedAStatus AidlCameraDeviceUser::isPrimaryClient(bool* _aidl_return) {
+ bool isPrimary;
+ UStatus ret = mDeviceRemote->isPrimaryClient(&isPrimary);
+ if (!ret.isOk()) {
+ ALOGE("%s: Failed to get isPrimaryClient: %s", __FUNCTION__, ret.toString8().c_str());
+ }
+ *_aidl_return = isPrimary;
+ return fromUStatus(ret);
+}
+
ndk::ScopedAStatus AidlCameraDeviceUser::flush(int64_t* _aidl_return) {
UStatus ret = mDeviceRemote->flush(_aidl_return);
return fromUStatus(ret);
@@ -278,4 +288,4 @@
return true;
}
-} // namespace android::frameworks::cameraservice::device::implementation
\ No newline at end of file
+} // namespace android::frameworks::cameraservice::device::implementation
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h
index 8014951..8fa33f7 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h
@@ -97,6 +97,8 @@
return mCaptureResultMetadataQueue;
}
+ ndk::ScopedAStatus isPrimaryClient(bool* _aidl_return) override;
+
private:
bool initDevice();
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.cpp b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
index 7f674bd..a2c431e 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraService.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
@@ -30,6 +30,9 @@
#include <hidl/HidlTransportSupport.h>
#include <utils/AttributionAndPermissionUtils.h>
#include <utils/Utils.h>
+#include <com_android_internal_camera_flags.h>
+
+namespace flags = com::android::internal::camera::flags;
namespace android::frameworks::cameraservice::service::implementation {
@@ -131,10 +134,28 @@
return ScopedAStatus::ok();
}
+
ndk::ScopedAStatus AidlCameraService::connectDevice(
const std::shared_ptr<SICameraDeviceCallback>& in_callback,
const std::string& in_cameraId,
std::shared_ptr<SICameraDeviceUser>* _aidl_return) {
+ return connectDeviceImpl(in_callback, in_cameraId, /*sharedMode*/false, _aidl_return);
+}
+
+ndk::ScopedAStatus AidlCameraService::connectDeviceV2(
+ const std::shared_ptr<SICameraDeviceCallback>& in_callback,
+ const std::string& in_cameraId, bool sharedMode,
+ std::shared_ptr<SICameraDeviceUser>* _aidl_return) {
+ if (!flags::camera_multi_client()) {
+ return fromSStatus(SStatus::INVALID_OPERATION);
+ }
+ return connectDeviceImpl(in_callback, in_cameraId, sharedMode, _aidl_return);
+}
+
+ndk::ScopedAStatus AidlCameraService::connectDeviceImpl(
+ const std::shared_ptr<SICameraDeviceCallback>& in_callback,
+ const std::string& in_cameraId, bool sharedMode,
+ std::shared_ptr<SICameraDeviceUser>* _aidl_return) {
// Here, we first get NDK ICameraDeviceUser from mCameraService, then save
// that interface in the newly created AidlCameraDeviceUser impl class.
if (mCameraService == nullptr) {
@@ -164,6 +185,7 @@
ROTATION_OVERRIDE_NONE,
clientAttribution,
/* devicePolicy= */ 0,
+ sharedMode,
&unstableDevice);
if (!serviceRet.isOk()) {
ALOGE("%s: Unable to connect to camera device: %s", __FUNCTION__,
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.h b/services/camera/libcameraservice/aidl/AidlCameraService.h
index 4c67ac7..80e965d 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraService.h
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.h
@@ -60,6 +60,9 @@
ndk::ScopedAStatus removeListener(
const std::shared_ptr<SICameraServiceListener>& in_listener) override;
+ ndk::ScopedAStatus connectDeviceV2(const std::shared_ptr<SICameraDeviceCallback>& in_callback,
+ const std::string& in_cameraId, bool sharedMode,
+ std::shared_ptr<SICameraDeviceUser>* _aidl_return);
private:
void addToListenerCacheLocked(std::shared_ptr<SICameraServiceListener> stableCsListener,
sp<hardware::ICameraServiceListener> csListener);
@@ -70,6 +73,9 @@
SStatus addListenerInternal(const std::shared_ptr<SICameraServiceListener>& listener,
std::vector<hardware::CameraStatus>* cameraStatusAndIds);
+ ndk::ScopedAStatus connectDeviceImpl(const std::shared_ptr<SICameraDeviceCallback>& in_callback,
+ const std::string& in_cameraId, bool sharedMode,
+ std::shared_ptr<SICameraDeviceUser>* _aidl_return);
::android::CameraService* mCameraService;
diff --git a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
index a7c32e3..c0dc688 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
@@ -75,6 +75,11 @@
uint32_t flags) override;
status_t unlinkToDeath(const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
wp<DeathRecipient>* outRecipient) override;
+ binder::Status onCameraOpenedInSharedMode(const std::string& /*cameraId*/,
+ const std::string& /*clientPackageId*/, int32_t /*deviceId*/, bool /*primaryClient*/) {
+ // empty implementation
+ return binder::Status::ok();
+ }
private:
std::shared_ptr<SICameraServiceListener> mBase;
@@ -86,4 +91,4 @@
} // android
-#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICELISTENER_H_
\ No newline at end of file
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICELISTENER_H_
diff --git a/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
index 1835f2f..43ddac6 100644
--- a/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
+++ b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
@@ -103,6 +103,8 @@
ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STALL_DURATIONS_MAXIMUM_RESOLUTION,
ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS,
ANDROID_HEIC_AVAILABLE_HEIC_ULTRA_HDR_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION,
+ ANDROID_SHARED_SESSION_COLOR_SPACE,
+ ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS,
} },
};
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 45b7c3b..1d29462 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -28,6 +28,7 @@
#include <camera/CameraUtils.h>
#include <camera/StringUtils.h>
#include <com_android_internal_camera_flags.h>
+#include <com_android_window_flags.h>
#include <cutils/properties.h>
#include <gui/Surface.h>
#include <gui/view/Surface.h>
@@ -53,6 +54,7 @@
using namespace camera2;
namespace flags = com::android::internal::camera::flags;
+namespace wm_flags = com::android::window::flags;
// Interface used by CameraService
@@ -63,12 +65,12 @@
const AttributionSourceState& clientAttribution, int callingPid,
const std::string& cameraDeviceId, int api1CameraId, int cameraFacing,
int sensorOrientation, int servicePid, bool overrideForPerfClass, int rotationOverride,
- bool forceSlowJpegMode)
+ bool forceSlowJpegMode, bool sharedMode)
: Camera2ClientBase(cameraService, cameraClient, cameraServiceProxyWrapper,
attributionAndPermissionUtils, clientAttribution, callingPid,
false /*systemNativeClient - since no ndk for api1*/, cameraDeviceId,
api1CameraId, cameraFacing, sensorOrientation, servicePid,
- overrideForPerfClass, rotationOverride,
+ overrideForPerfClass, rotationOverride, sharedMode,
/*legacyClient*/ true),
mParameters(api1CameraId, cameraFacing),
mLatestRequestIds(kMaxRequestIds),
@@ -134,8 +136,13 @@
// The 'mRotateAndCropMode' value only accounts for the necessary adjustment
// when the display rotates. The sensor orientation still needs to be calculated
// and applied similar to the Camera2 path.
+ using hardware::BnCameraService::ROTATION_OVERRIDE_ROTATION_ONLY;
+ bool enableTransformInverseDisplay = true;
+ if (wm_flags::enable_camera_compat_for_desktop_windowing()) {
+ enableTransformInverseDisplay = (mRotationOverride != ROTATION_OVERRIDE_ROTATION_ONLY);
+ }
CameraUtils::getRotationTransform(staticInfo, OutputConfiguration::MIRROR_MODE_AUTO,
- &mRotateAndCropPreviewTransform);
+ enableTransformInverseDisplay, &mRotateAndCropPreviewTransform);
mStreamingProcessor = new StreamingProcessor(this);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 345494b..51d8d54 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -107,7 +107,7 @@
const AttributionSourceState& clientAttribution, int callingPid,
const std::string& cameraDeviceId, int api1CameraId, int cameraFacing,
int sensorOrientation, int servicePid, bool overrideForPerfClass,
- int rotationOverride, bool forceSlowJpegMode);
+ int rotationOverride, bool forceSlowJpegMode, bool sharedMode);
virtual ~Camera2Client();
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 17a6dc3..8c30d54 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -63,10 +63,11 @@
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const AttributionSourceState& clientAttribution, int callingPid, bool systemNativeClient,
const std::string& cameraId, [[maybe_unused]] int api1CameraId, int cameraFacing,
- int sensorOrientation, int servicePid, int rotationOverride)
+ int sensorOrientation, int servicePid, int rotationOverride, bool sharedMode)
: BasicClient(cameraService, IInterface::asBinder(remoteCallback),
attributionAndPermissionUtils, clientAttribution, callingPid, systemNativeClient,
- cameraId, cameraFacing, sensorOrientation, servicePid, rotationOverride),
+ cameraId, cameraFacing, sensorOrientation, servicePid, rotationOverride,
+ sharedMode),
mRemoteCallback(remoteCallback) {}
// Interface used by CameraService
@@ -78,11 +79,13 @@
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const AttributionSourceState& clientAttribution, int callingPid, bool systemNativeClient,
const std::string& cameraId, int cameraFacing, int sensorOrientation, int servicePid,
- bool overrideForPerfClass, int rotationOverride, const std::string& originalCameraId)
+ bool overrideForPerfClass, int rotationOverride, const std::string& originalCameraId,
+ bool sharedMode)
: Camera2ClientBase(cameraService, remoteCallback, cameraServiceProxyWrapper,
attributionAndPermissionUtils, clientAttribution, callingPid,
systemNativeClient, cameraId, /*API1 camera ID*/ -1, cameraFacing,
- sensorOrientation, servicePid, overrideForPerfClass, rotationOverride),
+ sensorOrientation, servicePid, overrideForPerfClass, rotationOverride,
+ sharedMode),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0),
@@ -610,9 +613,20 @@
}
binder::Status CameraDeviceClient::beginConfigure() {
- // TODO: Implement this.
ATRACE_CALL();
- ALOGV("%s: Not implemented yet.", __FUNCTION__);
+ if (!flags::camera_multi_client()) {
+ return binder::Status::ok();
+ }
+ if (!mDevice.get()) {
+ return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+ }
+ status_t res = mDevice->beginConfigure();
+ if (res != OK) {
+ std::string msg = fmt::sprintf("Camera %s: Error beginning stream configuration: %s (%d)",
+ mCameraIdStr.c_str(), strerror(-res), res);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
+ }
return binder::Status::ok();
}
@@ -645,6 +659,12 @@
return res;
}
+ if (flags::camera_multi_client() && mSharedMode) {
+ // For shared camera session, streams are already configured
+ // earlier, hence no need to do it here.
+ return res;
+ }
+
status_t err = mDevice->configureStreams(sessionParams, operatingMode);
if (err == BAD_VALUE) {
std::string msg = fmt::sprintf("Camera %s: Unsupported set of inputs/outputs provided",
@@ -768,6 +788,7 @@
bool isInput = false;
std::vector<sp<IBinder>> surfaces;
+ std::vector<size_t> removedSurfaceIds;
ssize_t dIndex = NAME_NOT_FOUND;
ssize_t compositeIndex = NAME_NOT_FOUND;
@@ -778,6 +799,9 @@
for (size_t i = 0; i < mStreamMap.size(); ++i) {
if (streamId == mStreamMap.valueAt(i).streamId()) {
surfaces.push_back(mStreamMap.keyAt(i));
+ if (flags::camera_multi_client() && mSharedMode) {
+ removedSurfaceIds.push_back(mStreamMap.valueAt(i).surfaceId());
+ }
}
}
@@ -805,8 +829,14 @@
}
}
- // Also returns BAD_VALUE if stream ID was not valid
- status_t err = mDevice->deleteStream(streamId);
+
+ status_t err;
+ if (flags::camera_multi_client() && mSharedMode) {
+ err = mDevice->removeSharedSurfaces(streamId, removedSurfaceIds);
+ } else {
+ // Also returns BAD_VALUE if stream ID was not valid
+ err = mDevice->deleteStream(streamId);
+ }
if (err != OK) {
std::string msg = fmt::sprintf("Camera %s: Unexpected error %s (%d) when deleting stream "
@@ -900,6 +930,7 @@
std::vector<SurfaceHolder> surfaces;
std::vector<sp<IBinder>> binders;
+ std::vector<OutputStreamInfo> streamInfos;
status_t err;
// Create stream for deferred surface case.
@@ -939,52 +970,57 @@
binders.push_back(IInterface::asBinder(bufferProducer));
surfaces.push_back({surface, mirrorMode});
+ if (flags::camera_multi_client() && mSharedMode) {
+ streamInfos.push_back(streamInfo);
+ }
}
- // If mOverrideForPerfClass is true, do not fail createStream() for small
- // JPEG sizes because existing createSurfaceFromGbp() logic will find the
- // closest possible supported size.
-
int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
std::vector<int> surfaceIds;
- bool isDepthCompositeStream =
- camera3::DepthCompositeStream::isDepthCompositeStream(surfaces[0].mSurface);
- bool isHeicCompositeStream = camera3::HeicCompositeStream::isHeicCompositeStream(
- surfaces[0].mSurface);
- bool isJpegRCompositeStream =
- camera3::JpegRCompositeStream::isJpegRCompositeStream(surfaces[0].mSurface) &&
- !mDevice->isCompositeJpegRDisabled();
- if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
- sp<CompositeStream> compositeStream;
- if (isDepthCompositeStream) {
- compositeStream = new camera3::DepthCompositeStream(mDevice, getRemoteCallback());
- } else if (isHeicCompositeStream) {
- compositeStream = new camera3::HeicCompositeStream(mDevice, getRemoteCallback());
- } else {
- compositeStream = new camera3::JpegRCompositeStream(mDevice, getRemoteCallback());
+ if (flags::camera_multi_client() && mSharedMode) {
+ err = mDevice->getSharedStreamId(outputConfiguration, &streamId);
+ if (err == OK) {
+ err = mDevice->addSharedSurfaces(streamId, streamInfos, surfaces, &surfaceIds);
}
-
- err = compositeStream->createStream(surfaces, deferredConsumer, streamInfo.width,
+ } else {
+ bool isDepthCompositeStream =
+ camera3::DepthCompositeStream::isDepthCompositeStream(surfaces[0].mSurface);
+ bool isHeicCompositeStream = camera3::HeicCompositeStream::isHeicCompositeStream(
+ surfaces[0].mSurface);
+ bool isJpegRCompositeStream =
+ camera3::JpegRCompositeStream::isJpegRCompositeStream(surfaces[0].mSurface) &&
+ !mDevice->isCompositeJpegRDisabled();
+ if (isDepthCompositeStream || isHeicCompositeStream || isJpegRCompositeStream) {
+ sp<CompositeStream> compositeStream;
+ if (isDepthCompositeStream) {
+ compositeStream = new camera3::DepthCompositeStream(mDevice, getRemoteCallback());
+ } else if (isHeicCompositeStream) {
+ compositeStream = new camera3::HeicCompositeStream(mDevice, getRemoteCallback());
+ } else {
+ compositeStream = new camera3::JpegRCompositeStream(mDevice, getRemoteCallback());
+ }
+ err = compositeStream->createStream(surfaces, deferredConsumer, streamInfo.width,
streamInfo.height, streamInfo.format,
static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
&streamId, physicalCameraId, streamInfo.sensorPixelModesUsed, &surfaceIds,
outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution,
streamInfo.colorSpace, streamInfo.dynamicRangeProfile, streamInfo.streamUseCase,
useReadoutTimestamp);
- if (err == OK) {
- Mutex::Autolock l(mCompositeLock);
- mCompositeStreamMap.add(
- IInterface::asBinder(surfaces[0].mSurface->getIGraphicBufferProducer()),
- compositeStream);
+ if (err == OK) {
+ Mutex::Autolock l(mCompositeLock);
+ mCompositeStreamMap.add(
+ IInterface::asBinder(surfaces[0].mSurface->getIGraphicBufferProducer()),
+ compositeStream);
+ }
+ } else {
+ err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
+ streamInfo.height, streamInfo.format, streamInfo.dataSpace,
+ static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
+ &streamId, physicalCameraId, streamInfo.sensorPixelModesUsed, &surfaceIds,
+ outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution,
+ /*consumerUsage*/0, streamInfo.dynamicRangeProfile, streamInfo.streamUseCase,
+ streamInfo.timestampBase, streamInfo.colorSpace, useReadoutTimestamp);
}
- } else {
- err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
- streamInfo.height, streamInfo.format, streamInfo.dataSpace,
- static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
- &streamId, physicalCameraId, streamInfo.sensorPixelModesUsed, &surfaceIds,
- outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution,
- /*consumerUsage*/0, streamInfo.dynamicRangeProfile, streamInfo.streamUseCase,
- streamInfo.timestampBase, streamInfo.colorSpace, useReadoutTimestamp);
}
if (err != OK) {
@@ -1743,6 +1779,20 @@
return binder::Status::ok();
}
+binder::Status CameraDeviceClient::isPrimaryClient(/*out*/bool* isPrimary) {
+ ATRACE_CALL();
+ binder::Status res = binder::Status::ok();
+ if (!flags::camera_multi_client()) {
+ return res;
+ }
+ if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+ if (isPrimary != nullptr) {
+ status_t ret = BasicClient::isPrimaryClient(isPrimary);
+ return binder::Status::fromStatusT(ret);
+ }
+ return res;
+}
+
status_t CameraDeviceClient::setCameraServiceWatchdog(bool enabled) {
return mDevice->setCameraServiceWatchdog(enabled);
}
@@ -1875,7 +1925,7 @@
offlineClient = new CameraOfflineSessionClient(
sCameraService, offlineSession, offlineCompositeStreamMap, cameraCb,
mAttributionAndPermissionUtils, mClientAttribution, mCallingPid, mCameraIdStr,
- mCameraFacing, mOrientation, mServicePid);
+ mCameraFacing, mOrientation, mServicePid, /*sharedMode*/false);
ret = sCameraService->addOfflineClient(mCameraIdStr, offlineClient);
}
@@ -2078,46 +2128,59 @@
}
}
+void CameraDeviceClient::notifyClientSharedAccessPriorityChanged(bool primaryClient) {
+ // Thread safe. Don't bother locking.
+ if (!flags::camera_multi_client()) {
+ return;
+ }
+ sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
+ if (remoteCb != 0) {
+ remoteCb->onClientSharedAccessPriorityChanged(primaryClient);
+ }
+}
+
void CameraDeviceClient::detachDevice() {
if (mDevice == 0) return;
nsecs_t startTime = systemTime();
- ALOGV("Camera %s: Stopping processors", mCameraIdStr.c_str());
+ if (!flags::camera_multi_client() || sCameraService->isOnlyClient(this)){
+ ALOGV("Camera %s: Stopping processors", mCameraIdStr.c_str());
- if (mFrameProcessor.get() != nullptr) {
- mFrameProcessor->removeListener(
- camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
- camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID, /*listener*/this);
- mFrameProcessor->requestExit();
- ALOGV("Camera %s: Waiting for threads", mCameraIdStr.c_str());
- mFrameProcessor->join();
- ALOGV("Camera %s: Disconnecting device", mCameraIdStr.c_str());
- }
-
- // WORKAROUND: HAL refuses to disconnect while there's streams in flight
- {
- int64_t lastFrameNumber;
- status_t code;
- if ((code = mDevice->flush(&lastFrameNumber)) != OK) {
- ALOGE("%s: flush failed with code 0x%x", __FUNCTION__, code);
+ if (mFrameProcessor.get() != nullptr) {
+ mFrameProcessor->removeListener(
+ camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MIN_ID,
+ camera2::FrameProcessorBase::FRAME_PROCESSOR_LISTENER_MAX_ID, /*listener*/this);
+ mFrameProcessor->requestExit();
+ ALOGV("Camera %s: Waiting for threads", mCameraIdStr.c_str());
+ mFrameProcessor->join();
+ ALOGV("Camera %s: Disconnecting device", mCameraIdStr.c_str());
}
- if ((code = mDevice->waitUntilDrained()) != OK) {
- ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
- code);
- }
- }
+ // WORKAROUND: HAL refuses to disconnect while there's streams in flight
+ {
+ int64_t lastFrameNumber;
+ status_t code;
+ if ((code = mDevice->flush(&lastFrameNumber)) != OK) {
+ ALOGE("%s: flush failed with code 0x%x", __FUNCTION__, code);
+ }
- {
- Mutex::Autolock l(mCompositeLock);
- for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
- auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
- if (ret != OK) {
- ALOGE("%s: Failed removing composite stream %s (%d)", __FUNCTION__,
- strerror(-ret), ret);
+ if ((code = mDevice->waitUntilDrained()) != OK) {
+ ALOGE("%s: waitUntilDrained failed with code 0x%x", __FUNCTION__,
+ code);
}
}
- mCompositeStreamMap.clear();
+
+ {
+ Mutex::Autolock l(mCompositeLock);
+ for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
+ auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
+ if (ret != OK) {
+ ALOGE("%s: Failed removing composite stream %s (%d)", __FUNCTION__,
+ strerror(-ret), ret);
+ }
+ }
+ mCompositeStreamMap.clear();
+ }
}
bool hasDeviceError = mDevice->hasDeviceError();
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 0858633..a8cf451 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -54,7 +54,8 @@
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const AttributionSourceState& clientAttribution, int callingPid,
bool systemNativeClient, const std::string& cameraId, int api1CameraId,
- int cameraFacing, int sensorOrientation, int servicePid, int rotationOverride);
+ int cameraFacing, int sensorOrientation, int servicePid, int rotationOverride,
+ bool sharedMode);
sp<hardware::camera2::ICameraDeviceCallbacks> mRemoteCallback;
};
@@ -168,6 +169,8 @@
/*out*/
sp<hardware::camera2::ICameraOfflineSession>* session) override;
+ virtual binder::Status isPrimaryClient(/*out*/bool* isPrimary) override;
+
/**
* Interface used by CameraService
*/
@@ -179,7 +182,7 @@
const AttributionSourceState& clientAttribution, int callingPid,
bool clientPackageOverride, const std::string& cameraId, int cameraFacing,
int sensorOrientation, int servicePid, bool overrideForPerfClass,
- int rotationOverride, const std::string& originalCameraId);
+ int rotationOverride, const std::string& originalCameraId, bool sharedMode);
virtual ~CameraDeviceClient();
virtual status_t initialize(sp<CameraProviderManager> manager,
@@ -222,6 +225,7 @@
virtual void notifyPrepared(int streamId);
virtual void notifyRequestQueueEmpty();
virtual void notifyRepeatingRequestError(long lastFrameNumber);
+ virtual void notifyClientSharedAccessPriorityChanged(bool primaryClient);
void setImageDumpMask(int mask) { if (mDevice != nullptr) mDevice->setImageDumpMask(mask); }
/**
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index e783cbc..71fd3ba 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -308,6 +308,9 @@
}
}
+void CameraOfflineSessionClient::notifyClientSharedAccessPriorityChanged(bool /*primaryClient*/) {
+}
+
void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& resultExtras,
nsecs_t timestamp) {
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index 574ff9a..78a3055 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -49,13 +49,14 @@
const sp<ICameraDeviceCallbacks>& remoteCallback,
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const AttributionSourceState& clientAttribution, int callingPid,
- const std::string& cameraIdStr, int cameraFacing, int sensorOrientation, int servicePid)
+ const std::string& cameraIdStr, int cameraFacing, int sensorOrientation, int servicePid,
+ bool sharedMode)
: CameraService::BasicClient(cameraService, IInterface::asBinder(remoteCallback),
attributionAndPermissionUtils,
// (v)ndk doesn't have offline session support
clientAttribution, callingPid, /*overridePackageName*/ false,
cameraIdStr, cameraFacing, sensorOrientation, servicePid,
- hardware::ICameraService::ROTATION_OVERRIDE_NONE),
+ hardware::ICameraService::ROTATION_OVERRIDE_NONE, sharedMode),
mRemoteCallback(remoteCallback),
mOfflineSession(session),
mCompositeStreamMap(offlineCompositeStreamMap) {}
@@ -119,6 +120,7 @@
void notifyRepeatingRequestError(long lastFrameNumber) override;
status_t injectCamera(const std::string& injectedCamId,
sp<CameraProviderManager> manager) override;
+ void notifyClientSharedAccessPriorityChanged(bool primaryClient) override;
status_t stopInjection() override;
status_t injectSessionParams(
const hardware::camera2::impl::CameraMetadataNative& sessionParams) override;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index f6b1e80..03abf71 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -31,6 +31,7 @@
#include <camera/CameraSessionStats.h>
#include <camera/StringUtils.h>
#include <com_android_window_flags.h>
+#include <com_android_internal_camera_flags.h>
#include "common/Camera2ClientBase.h"
@@ -39,12 +40,14 @@
#include "device3/Camera3Device.h"
#include "device3/aidl/AidlCamera3Device.h"
#include "device3/hidl/HidlCamera3Device.h"
+#include "device3/aidl/AidlCamera3SharedDevice.h"
namespace android {
using namespace camera2;
namespace wm_flags = com::android::window::flags;
+namespace flags = com::android::internal::camera::flags;
// Interface used by CameraService
@@ -55,10 +58,11 @@
std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
const AttributionSourceState& clientAttribution, int callingPid, bool systemNativeClient,
const std::string& cameraId, int api1CameraId, int cameraFacing, int sensorOrientation,
- int servicePid, bool overrideForPerfClass, int rotationOverride, bool legacyClient)
+ int servicePid, bool overrideForPerfClass, int rotationOverride, bool sharedMode,
+ bool legacyClient)
: TClientBase(cameraService, remoteCallback, attributionAndPermissionUtils, clientAttribution,
callingPid, systemNativeClient, cameraId, api1CameraId, cameraFacing,
- sensorOrientation, servicePid, rotationOverride),
+ sensorOrientation, servicePid, rotationOverride, sharedMode),
mSharedCameraCallbacks(remoteCallback),
mCameraServiceProxyWrapper(cameraServiceProxyWrapper),
mDeviceActive(false),
@@ -114,12 +118,19 @@
TClientBase::mRotationOverride, mLegacyClient);
break;
case IPCTransport::AIDL:
- mDevice =
+ if (flags::camera_multi_client() && TClientBase::mSharedMode) {
+ mDevice = AidlCamera3SharedDevice::getInstance(mCameraServiceProxyWrapper,
+ TClientBase::mAttributionAndPermissionUtils,
+ TClientBase::mCameraIdStr, mOverrideForPerfClass,
+ TClientBase::mRotationOverride, mLegacyClient);
+ } else {
+ mDevice =
new AidlCamera3Device(mCameraServiceProxyWrapper,
TClientBase::mAttributionAndPermissionUtils,
TClientBase::mCameraIdStr, mOverrideForPerfClass,
TClientBase::mRotationOverride, mLegacyClient);
- break;
+ }
+ break;
default:
ALOGE("%s Invalid transport for camera id %s", __FUNCTION__,
TClientBase::mCameraIdStr.c_str());
@@ -161,9 +172,10 @@
Camera2ClientBase<TClientBase>::~Camera2ClientBase() {
ATRACE_CALL();
- TClientBase::mDestructionStarted = true;
-
- disconnect();
+ if (!flags::camera_multi_client() || !TClientBase::mDisconnected) {
+ TClientBase::mDestructionStarted = true;
+ disconnect();
+ }
ALOGI("%s: Client object's dtor for Camera Id %s completed. Client was: %s (PID %d, UID %u)",
__FUNCTION__, TClientBase::mCameraIdStr.c_str(), TClientBase::getPackageName().c_str(),
@@ -250,7 +262,10 @@
template <typename TClientBase>
binder::Status Camera2ClientBase<TClientBase>::disconnect() {
- return disconnectImpl();
+ if (!flags::camera_multi_client() || !TClientBase::mDisconnected) {
+ return disconnectImpl();
+ }
+ return binder::Status::ok();
}
template <typename TClientBase>
@@ -288,7 +303,11 @@
template <typename TClientBase>
void Camera2ClientBase<TClientBase>::detachDevice() {
if (mDevice == 0) return;
- mDevice->disconnect();
+ if (flags::camera_multi_client() && TClientBase::mSharedMode) {
+ mDevice->disconnectClient(TClientBase::getClientUid());
+ } else {
+ mDevice->disconnect();
+ }
ALOGV("Camera %s: Detach complete", TClientBase::mCameraIdStr.c_str());
}
@@ -331,6 +350,12 @@
}
template <typename TClientBase>
+void Camera2ClientBase<TClientBase>::notifyClientSharedAccessPriorityChanged(bool primaryClient) {
+ ALOGV("%s Camera %s access priorities changed for client %d primaryClient=%d", __FUNCTION__,
+ TClientBase::mCameraIdStr.c_str(), TClientBase::getClientUid(), primaryClient);
+}
+
+template <typename TClientBase>
void Camera2ClientBase<TClientBase>::notifyPhysicalCameraChange(const std::string &physicalId) {
using android::hardware::ICameraService;
// We're only interested in this notification if rotationOverride is turned on.
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index e231f1f..cb30199 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -56,7 +56,8 @@
const AttributionSourceState& clientAttribution, int callingPid,
bool systemNativeClient, const std::string& cameraId, int api1CameraId,
int cameraFacing, int sensorOrientation, int servicePid,
- bool overrideForPerfClass, int rotationOverride, bool legacyClient = false);
+ bool overrideForPerfClass, int rotationOverride, bool sharedMode,
+ bool legacyClient = false);
virtual ~Camera2ClientBase();
virtual status_t initialize(sp<CameraProviderManager> manager,
@@ -88,6 +89,7 @@
virtual void notifyPrepared(int streamId);
virtual void notifyRequestQueueEmpty();
virtual void notifyRepeatingRequestError(long lastFrameNumber);
+ virtual void notifyClientSharedAccessPriorityChanged(bool primaryClient) override;
void notifyIdleWithUserTag(int64_t requestCount, int64_t resultErrorCount,
bool deviceError,
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index e17d700..cfedf0c 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -51,6 +51,7 @@
typedef enum camera_stream_configuration_mode {
CAMERA_STREAM_CONFIGURATION_NORMAL_MODE = 0,
CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE = 1,
+ CAMERA_STREAM_CONFIGURATION_SHARED_MODE = 2,
CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START = 0x8000
} camera_stream_configuration_mode_t;
@@ -97,6 +98,7 @@
virtual status_t initialize(sp<CameraProviderManager> manager,
const std::string& monitorTags) = 0;
virtual status_t disconnect() = 0;
+ virtual status_t disconnectClient(int) {return OK;};
virtual status_t dump(int fd, const Vector<String16> &args) = 0;
virtual status_t startWatchingTags(const std::string &tags) = 0;
@@ -290,6 +292,33 @@
*/
virtual status_t deleteStream(int id) = 0;
+
+ /**
+ * This function is responsible for configuring camera streams at the start of a session.
+ * In shared session mode, where multiple clients may access the camera, camera service
+ * applies a predetermined shared session configuration. If the camera is opened in non-shared
+ * mode, this function is a no-op.
+ */
+ virtual status_t beginConfigure() = 0;
+
+ /**
+ * In shared session mode, this function retrieves the stream ID associated with a specific
+ * output configuration.
+ */
+ virtual status_t getSharedStreamId(const OutputConfiguration &config, int *streamId) = 0;
+
+ /**
+ * In shared session mode, this function add surfaces to an existing shared stream ID.
+ */
+ virtual status_t addSharedSurfaces(int streamId,
+ const std::vector<android::camera3::OutputStreamInfo> &outputInfo,
+ const std::vector<SurfaceHolder>& surfaces, std::vector<int> *surfaceIds = nullptr) = 0;
+
+ /**
+ * In shared session mode, this function remove surfaces from an existing shared stream ID.
+ */
+ virtual status_t removeSharedSurfaces(int streamId, const std::vector<size_t> &surfaceIds) = 0;
+
/**
* Take the currently-defined set of streams and configure the HAL to use
* them. This is a long-running operation (may be several hundered ms).
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 48f43e6..a8d7480 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -63,6 +63,7 @@
using namespace camera3::SessionConfigurationUtils;
using std::literals::chrono_literals::operator""s;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+using hardware::camera2::params::OutputConfiguration;
namespace flags = com::android::internal::camera::flags;
namespace vd_flags = android::companion::virtualdevice::flags;
@@ -2081,6 +2082,75 @@
return res;
}
+bool CameraProviderManager::ProviderInfo::DeviceInfo3::isAutomotiveDevice() {
+ // Checks the property ro.hardware.type and returns true if it is
+ // automotive.
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.hardware.type", value, "");
+ return strncmp(value, "automotive", PROPERTY_VALUE_MAX) == 0;
+}
+
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::addSharedSessionConfigurationTags() {
+ status_t res = OK;
+ if (flags::camera_multi_client()) {
+ const int32_t sharedColorSpaceTag = ANDROID_SHARED_SESSION_COLOR_SPACE;
+ const int32_t sharedOutputConfigurationsTag = ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS;
+ auto& c = mCameraCharacteristics;
+ uint8_t colorSpace = 0;
+
+ res = c.update(sharedColorSpaceTag, &colorSpace, 1);
+
+ // ToDo: b/372321187 Hardcoding the shared session configuration. Update the code to
+ // take these values from XML instead.
+ std::vector<int64_t> sharedOutputConfigEntries;
+ int64_t surfaceType1 = OutputConfiguration::SURFACE_TYPE_IMAGE_READER;
+ int64_t width = 1280;
+ int64_t height = 800;
+ int64_t format1 = HAL_PIXEL_FORMAT_RGBA_8888;
+ int64_t mirrorMode = OutputConfiguration::MIRROR_MODE_AUTO;
+ int64_t timestampBase = OutputConfiguration::TIMESTAMP_BASE_DEFAULT;
+ int64_t usage1 = 3;
+ int64_t dataspace = 0;
+ int64_t useReadoutTimestamp = 0;
+ int64_t streamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
+ int64_t physicalCamIdLen = 0;
+
+ // Stream 1 configuration hardcoded
+ sharedOutputConfigEntries.push_back(surfaceType1);
+ sharedOutputConfigEntries.push_back(width);
+ sharedOutputConfigEntries.push_back(height);
+ sharedOutputConfigEntries.push_back(format1);
+ sharedOutputConfigEntries.push_back(mirrorMode);
+ sharedOutputConfigEntries.push_back(useReadoutTimestamp);
+ sharedOutputConfigEntries.push_back(timestampBase);
+ sharedOutputConfigEntries.push_back(dataspace);
+ sharedOutputConfigEntries.push_back(usage1);
+ sharedOutputConfigEntries.push_back(streamUseCase);
+ sharedOutputConfigEntries.push_back(physicalCamIdLen);
+
+ // Stream 2 configuration hardcoded
+ int64_t surfaceType2 = OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW;
+ int64_t format2 = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+ int64_t usage2 = 0;
+
+ sharedOutputConfigEntries.push_back(surfaceType2);
+ sharedOutputConfigEntries.push_back(width);
+ sharedOutputConfigEntries.push_back(height);
+ sharedOutputConfigEntries.push_back(format2);
+ sharedOutputConfigEntries.push_back(mirrorMode);
+ sharedOutputConfigEntries.push_back(useReadoutTimestamp);
+ sharedOutputConfigEntries.push_back(timestampBase);
+ sharedOutputConfigEntries.push_back(dataspace);
+ sharedOutputConfigEntries.push_back(usage2);
+ sharedOutputConfigEntries.push_back(streamUseCase);
+ sharedOutputConfigEntries.push_back(physicalCamIdLen);
+
+ res = c.update(sharedOutputConfigurationsTag, sharedOutputConfigEntries.data(),
+ sharedOutputConfigEntries.size());
+ }
+ return res;
+}
+
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::removeAvailableKeys(
CameraMetadata& c, const std::vector<uint32_t>& keys, uint32_t keyTag) {
status_t res = OK;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 803df40..11985f5 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -782,6 +782,8 @@
status_t addColorCorrectionAvailableModesTag(CameraMetadata& ch);
status_t addAePriorityModeTags();
status_t addSessionConfigQueryVersionTag();
+ status_t addSharedSessionConfigurationTags();
+ bool isAutomotiveDevice();
static void getSupportedSizes(const CameraMetadata& ch, uint32_t tag,
android_pixel_format_t format,
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 3a0cfa1..88998c6 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -30,6 +30,7 @@
#include "device3/DistortionMapper.h"
#include "device3/ZoomRatioMapper.h"
+#include <utils/AttributionAndPermissionUtils.h>
#include <utils/SessionConfigurationUtils.h>
#include <utils/Trace.h>
@@ -202,7 +203,7 @@
void AidlProviderInfo::binderDied(void *cookie) {
AidlProviderInfo *provider = reinterpret_cast<AidlProviderInfo *>(cookie);
ALOGI("Camera provider '%s' has died; removing it", provider->mProviderInstance.c_str());
- provider->mManager->removeProvider(provider->mProviderInstance);
+ provider->mManager->removeProvider(std::string(provider->mProviderInstance));
}
status_t AidlProviderInfo::setUpVendorTags() {
@@ -320,7 +321,7 @@
if (link != STATUS_OK) {
ALOGW("%s: Unable to link to provider '%s' death notifications",
__FUNCTION__, mProviderName.c_str());
- mManager->removeProvider(mProviderInstance);
+ mManager->removeProvider(std::string(mProviderInstance));
return nullptr;
}
@@ -732,6 +733,10 @@
{ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, ANDROID_CONTROL_AE_TARGET_FPS_RANGE});
}
+ if (flags::camera_multi_client() && isAutomotiveDevice()) {
+ addSharedSessionConfigurationTags();
+ }
+
if (!kEnableLazyHal) {
// Save HAL reference indefinitely
mSavedInterface = interface;
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index 756c255..27ae766 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -391,7 +391,7 @@
__FUNCTION__,
mProviderName.c_str(),
linked.description().c_str());
- mManager->removeProvider(mProviderInstance);
+ mManager->removeProvider(std::string(mProviderInstance));
return nullptr;
} else if (!linked) {
ALOGW("%s: Unable to link to provider '%s' death notifications",
@@ -451,7 +451,7 @@
ALOGW("%s: Unexpected serviceDied cookie %" PRIu64 ", expected %" PRIu32,
__FUNCTION__, cookie, mId);
}
- mManager->removeProvider(mProviderInstance);
+ mManager->removeProvider(std::string(mProviderInstance));
}
std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 35a192f..c6434a5 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -58,6 +58,7 @@
#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
#include <com_android_internal_camera_flags.h>
+#include <com_android_window_flags.h>
#include "CameraService.h"
#include "aidl/android/hardware/graphics/common/Dataspace.h"
@@ -83,6 +84,8 @@
using namespace android::hardware::cameraservice::utils::conversion::aidl;
namespace flags = com::android::internal::camera::flags;
+namespace wm_flags = com::android::window::flags;
+
namespace android {
Camera3Device::Camera3Device(std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
@@ -5820,7 +5823,13 @@
status_t Camera3Device::deriveAndSetTransformLocked(
Camera3OutputStreamInterface& stream, int mirrorMode, int surfaceId) {
int transform = -1;
- int res = CameraUtils::getRotationTransform(mDeviceInfo, mirrorMode, &transform);
+ bool enableTransformInverseDisplay = true;
+ using hardware::ICameraService::ROTATION_OVERRIDE_ROTATION_ONLY;
+ if (wm_flags::enable_camera_compat_for_desktop_windowing()) {
+ enableTransformInverseDisplay = (mRotationOverride != ROTATION_OVERRIDE_ROTATION_ONLY);
+ }
+ int res = CameraUtils::getRotationTransform(mDeviceInfo, mirrorMode,
+ enableTransformInverseDisplay, &transform);
if (res != OK) {
return res;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index f1e088e..fad3f53 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -195,6 +195,19 @@
status_t deleteStream(int id) override;
+ virtual status_t beginConfigure() override {return OK;};
+
+ virtual status_t getSharedStreamId(const OutputConfiguration& /*config*/,
+ int* /*streamId*/) override {return INVALID_OPERATION;};
+
+ virtual status_t addSharedSurfaces(int /*streamId*/,
+ const std::vector<android::camera3::OutputStreamInfo>& /*outputInfo*/,
+ const std::vector<SurfaceHolder>& /*surfaces*/,
+ std::vector<int>* /*surfaceIds*/) override {return INVALID_OPERATION;};
+
+ virtual status_t removeSharedSurfaces(int /*streamId*/,
+ const std::vector<size_t>& /*surfaceIds*/) override {return INVALID_OPERATION;};
+
status_t configureStreams(const CameraMetadata& sessionParams,
int operatingMode =
camera_stream_configuration_mode_t::CAMERA_STREAM_CONFIGURATION_NORMAL_MODE) override;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index 66ffc98..78f1698 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -687,7 +687,8 @@
if (orientation.count > 0) {
int32_t transform;
ret = CameraUtils::getRotationTransform(deviceInfo->second,
- OutputConfiguration::MIRROR_MODE_AUTO, &transform);
+ OutputConfiguration::MIRROR_MODE_AUTO,
+ /*transformInverseDisplay*/true, &transform);
if (ret == OK) {
// It is possible for camera providers to return the capture
// results after the processed frames. In such scenario, we will
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
index abc3f9c..474dfc7 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -72,7 +72,8 @@
virtual status_t switchToOffline(const std::vector<int32_t>& /*streamsToKeep*/,
/*out*/ sp<CameraOfflineSessionBase>* /*session*/) override;
- status_t initialize(sp<CameraProviderManager> manager, const std::string& monitorTags) override;
+ virtual status_t initialize(sp<CameraProviderManager> manager, const std::string& monitorTags)
+ override;
class AidlHalInterface : public Camera3Device::HalInterface {
public:
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.cpp
new file mode 100644
index 0000000..5bd8d8c
--- /dev/null
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.cpp
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "AidlCamera3-SharedDevice"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0 // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+// Convenience macro for transient errors
+#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.c_str(), __FUNCTION__, \
+ ##__VA_ARGS__)
+
+#define CLOGW(fmt, ...) ALOGW("Camera %s: %s: " fmt, mId.c_str(), __FUNCTION__, \
+ ##__VA_ARGS__)
+
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) setErrorState( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+#define DECODE_VALUE(decoder, type, var) \
+ do { \
+ if (decoder.get##type(var) != OK) { \
+ return NOT_ENOUGH_DATA; \
+ } \
+ } while (0)
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <cstring>
+#include "../../common/aidl/AidlProviderInfo.h"
+#include "utils/SessionConfigurationUtils.h"
+#include "AidlCamera3SharedDevice.h"
+
+using namespace android::camera3;
+using namespace android::camera3::SessionConfigurationUtils;
+
+namespace android {
+
+// Metadata android.info.availableSharedOutputConfigurations has list of shared output
+// configurations. Each output configuration has minimum of 11 entries of size long
+// followed by the physical camera id if present.
+// See android.info.availableSharedOutputConfigurations for details.
+static const int SHARED_OUTPUT_CONFIG_NUM_OF_ENTRIES = 11;
+std::map<std::string, sp<AidlCamera3SharedDevice>> AidlCamera3SharedDevice::sSharedDevices;
+std::map<std::string, std::unordered_set<int>> AidlCamera3SharedDevice::sClientsUid;
+sp<AidlCamera3SharedDevice> AidlCamera3SharedDevice::getInstance(
+ std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+ std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
+ const std::string& id, bool overrideForPerfClass, int rotationOverride,
+ bool legacyClient) {
+ if (sClientsUid[id].empty()) {
+ AidlCamera3SharedDevice* sharedDevice = new AidlCamera3SharedDevice(
+ cameraServiceProxyWrapper, attributionAndPermissionUtils, id, overrideForPerfClass,
+ rotationOverride, legacyClient);
+ sSharedDevices[id] = sharedDevice;
+ }
+ if (attributionAndPermissionUtils != nullptr) {
+ sClientsUid[id].insert(attributionAndPermissionUtils->getCallingUid());
+ }
+ return sSharedDevices[id];
+}
+
+status_t AidlCamera3SharedDevice::initialize(sp<CameraProviderManager> manager,
+ const std::string& monitorTags) {
+ ATRACE_CALL();
+ status_t res = OK;
+
+ if (mStatus == STATUS_UNINITIALIZED) {
+ res = AidlCamera3Device::initialize(manager, monitorTags);
+ if (res == OK) {
+ mSharedOutputConfigurations = getSharedOutputConfiguration();
+ }
+ }
+ return res;
+}
+
+status_t AidlCamera3SharedDevice::disconnectClient(int clientUid) {
+ if (sClientsUid[mId].erase(clientUid) == 0) {
+ ALOGW("%s: Camera %s: Client %d is not connected to shared device", __FUNCTION__,
+ mId.c_str(), clientUid);
+ }
+ if (sClientsUid[mId].empty()) {
+ return Camera3Device::disconnect();
+ }
+ return OK;
+}
+
+std::vector<OutputConfiguration> AidlCamera3SharedDevice::getSharedOutputConfiguration() {
+ std::vector<OutputConfiguration> sharedConfigs;
+ uint8_t colorspace = ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED;
+ camera_metadata_entry sharedSessionColorSpace = mDeviceInfo.find(
+ ANDROID_SHARED_SESSION_COLOR_SPACE);
+ if (sharedSessionColorSpace.count > 0) {
+ colorspace = *sharedSessionColorSpace.data.u8;
+ }
+ camera_metadata_entry sharedSessionConfigs = mDeviceInfo.find(
+ ANDROID_SHARED_SESSION_OUTPUT_CONFIGURATIONS);
+ if (sharedSessionConfigs.count > 0) {
+ int numOfEntries = sharedSessionConfigs.count;
+ int i = 0;
+ uint8_t physicalCameraIdLen;
+ int surfaceType, width, height, format, mirrorMode, timestampBase, dataspace;
+ long usage, streamUseCase;
+ bool isReadOutTimestampEnabled;
+ while (numOfEntries >= SHARED_OUTPUT_CONFIG_NUM_OF_ENTRIES) {
+ surfaceType = (int)sharedSessionConfigs.data.i64[i];
+ width = (int)sharedSessionConfigs.data.i64[i+1];
+ height = (int)sharedSessionConfigs.data.i64[i+2];
+ format = (int)sharedSessionConfigs.data.i64[i+3];
+ mirrorMode = (int)sharedSessionConfigs.data.i64[i+4];
+ isReadOutTimestampEnabled = (sharedSessionConfigs.data.i64[i+5] != 0);
+ timestampBase = (int)sharedSessionConfigs.data.i64[i+6];
+ dataspace = (int)sharedSessionConfigs.data.i64[i+7];
+ usage = sharedSessionConfigs.data.i64[i+8];
+ streamUseCase = sharedSessionConfigs.data.i64[i+9];
+ physicalCameraIdLen = sharedSessionConfigs.data.i64[i+10];
+ numOfEntries -= SHARED_OUTPUT_CONFIG_NUM_OF_ENTRIES;
+ i += SHARED_OUTPUT_CONFIG_NUM_OF_ENTRIES;
+ if (numOfEntries < physicalCameraIdLen) {
+ ALOGE("%s: Camera %s: Number of remaining data (%d entries) in shared configuration"
+ " is less than physical camera id length %d. Malformed metadata"
+ " android.info.availableSharedOutputConfigurations.", __FUNCTION__,
+ mId.c_str(), numOfEntries, physicalCameraIdLen);
+ break;
+ }
+ std::string physicalCameraId;
+ long asciiValue;
+ for (int j = 0; j < physicalCameraIdLen; j++) {
+ asciiValue = sharedSessionConfigs.data.i64[i+j];
+ if (asciiValue == 0) { // Check for null terminator
+ break;
+ }
+ physicalCameraId += static_cast<char>(asciiValue);
+ }
+ OutputConfiguration* outConfig = new OutputConfiguration(surfaceType, width, height,
+ format, colorspace, mirrorMode, isReadOutTimestampEnabled, timestampBase,
+ dataspace, usage, streamUseCase, physicalCameraId);
+ sharedConfigs.push_back(*outConfig);
+ i += physicalCameraIdLen;
+ numOfEntries -= physicalCameraIdLen;
+ }
+ if (numOfEntries != 0) {
+ ALOGE("%s: Camera %s: there are still %d entries left in shared output configuration."
+ " Malformed metadata android.info.availableSharedOutputConfigurations.",
+ __FUNCTION__, mId.c_str(), numOfEntries);
+ }
+ }
+ return sharedConfigs;
+}
+
+status_t AidlCamera3SharedDevice::beginConfigure() {
+ status_t res;
+ int i = 0;
+
+ if (mStatus != STATUS_UNCONFIGURED) {
+ return OK;
+ }
+
+ for (auto config : mSharedOutputConfigurations) {
+ std::vector<SurfaceHolder> consumers;
+ android_dataspace dataSpace;
+ if (config.getColorSpace()
+ != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED
+ && config.getFormat() != HAL_PIXEL_FORMAT_BLOB) {
+ if (!dataSpaceFromColorSpace(&dataSpace, config.getColorSpace())) {
+ std::string msg = fmt::sprintf("Camera %s: color space %d not supported, "
+ " failed to convert to data space", mId.c_str(), config.getColorSpace());
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return INVALID_OPERATION;
+ }
+ }
+ std::unordered_set<int32_t> overriddenSensorPixelModes;
+ if (checkAndOverrideSensorPixelModesUsed(config.getSensorPixelModesUsed(),
+ config.getFormat(), config.getWidth(), config.getHeight(),
+ mDeviceInfo, &overriddenSensorPixelModes) != OK) {
+ std::string msg = fmt::sprintf("Camera %s: sensor pixel modes for stream with "
+ "format %#x are not valid",mId.c_str(), config.getFormat());
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return INVALID_OPERATION;
+ }
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ mSharedSurfaces[i] = new Surface(producer);
+ consumers.push_back({mSharedSurfaces[i], config.getMirrorMode()});
+ mSharedStreams[i] = new Camera3SharedOutputStream(mNextStreamId, consumers,
+ config.getWidth(),config.getHeight(), config.getFormat(), config.getUsage(),
+ dataSpace, static_cast<camera_stream_rotation_t>(config.getRotation()),
+ mTimestampOffset, config.getPhysicalCameraId(), overriddenSensorPixelModes,
+ getTransportType(), config.getSurfaceSetID(), mUseHalBufManager,
+ config.getDynamicRangeProfile(), config.getStreamUseCase(),
+ mDeviceTimeBaseIsRealtime, config.getTimestampBase(),
+ config.getColorSpace(), config.useReadoutTimestamp());
+ int id = mSharedStreams[i]->getSurfaceId(consumers[0].mSurface);
+ if (id < 0) {
+ SET_ERR_L("Invalid surface id");
+ return BAD_VALUE;
+ }
+ mSharedSurfaceIds[i] = id;
+ mSharedStreams[i]->setStatusTracker(mStatusTracker);
+ mSharedStreams[i]->setBufferManager(mBufferManager);
+ mSharedStreams[i]->setImageDumpMask(mImageDumpMask);
+ res = mOutputStreams.add(mNextStreamId, mSharedStreams[i]);
+ if (res < 0) {
+ SET_ERR_L("Can't add new stream to set: %s (%d)", strerror(-res), res);
+ return res;
+ }
+ mSessionStatsBuilder.addStream(mNextStreamId);
+ mConfiguredOutputs.add(mNextStreamId++, config);
+ i++;
+ }
+ CameraMetadata sessionParams;
+ res = configureStreams(sessionParams, CAMERA_STREAM_CONFIGURATION_SHARED_MODE);
+ if (res != OK) {
+ std::string msg = fmt::sprintf("Camera %s: Error configuring streams: %s (%d)",
+ mId.c_str(), strerror(-res), res);
+ ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+ return res;
+ }
+ return OK;
+}
+
+status_t AidlCamera3SharedDevice::getSharedStreamId(const OutputConfiguration &config,
+ int *streamId) {
+ if (streamId == nullptr) {
+ return BAD_VALUE;
+ }
+ for (size_t i = 0 ; i < mConfiguredOutputs.size(); i++){
+ OutputConfiguration sharedConfig = mConfiguredOutputs.valueAt(i);
+ if (config.sharedConfigEqual(sharedConfig)) {
+ *streamId = mConfiguredOutputs.keyAt(i);
+ return OK;
+ }
+ }
+ return INVALID_OPERATION;
+}
+
+status_t AidlCamera3SharedDevice::addSharedSurfaces(int streamId,
+ const std::vector<android::camera3::OutputStreamInfo> &outputInfo,
+ const std::vector<SurfaceHolder> &surfaces, std::vector<int> *surfaceIds) {
+ KeyedVector<sp<Surface>, size_t> outputMap;
+ std::vector<size_t> removedSurfaceIds;
+ status_t res;
+ sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
+ if (stream == nullptr) {
+ CLOGE("Stream %d is unknown", streamId);
+ return BAD_VALUE;
+ }
+
+ res = updateStream(streamId, surfaces, outputInfo, removedSurfaceIds, &outputMap);
+ if (res != OK) {
+ CLOGE("Stream %d failed to update stream (error %d %s) ",
+ streamId, res, strerror(-res));
+ return res;
+ }
+
+ for (size_t i = 0 ; i < outputMap.size(); i++){
+ if (surfaceIds != nullptr) {
+ surfaceIds->push_back(outputMap.valueAt(i));
+ }
+ }
+ return OK;
+}
+
+status_t AidlCamera3SharedDevice::removeSharedSurfaces(int streamId,
+ const std::vector<size_t> &removedSurfaceIds) {
+ KeyedVector<sp<Surface>, size_t> outputMap;
+ std::vector<SurfaceHolder> surfaces;
+ std::vector<OutputStreamInfo> outputInfo;
+ status_t res;
+ sp<Camera3OutputStreamInterface> stream = mOutputStreams.get(streamId);
+ if (stream == nullptr) {
+ CLOGE("Stream %d is unknown", streamId);
+ return BAD_VALUE;
+ }
+
+ res = updateStream(streamId, surfaces, outputInfo, removedSurfaceIds, &outputMap);
+ if (res != OK) {
+ CLOGE("Stream %d failed to update stream (error %d %s) ",
+ streamId, res, strerror(-res));
+ return res;
+ }
+ return OK;
+}
+}
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.h
new file mode 100644
index 0000000..b2ee2d6
--- /dev/null
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3SharedDevice.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#ifndef ANDROID_SERVERS_AIDLCAMERA3SHAREDDEVICE_H
+#define ANDROID_SERVERS_AIDLCAMERA3SHAREDDEVICE_H
+
+#include <camera/camera2/OutputConfiguration.h>
+#include "../Camera3SharedOutputStream.h"
+#include "AidlCamera3Device.h"
+namespace android {
+
+/**
+ * Shared CameraDevice for AIDL HAL devices.
+ */
+using ::android::camera3::Camera3SharedOutputStream;
+class AidlCamera3SharedDevice :
+ public AidlCamera3Device {
+ public:
+ static sp<AidlCamera3SharedDevice> getInstance(
+ std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+ std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
+ const std::string& id, bool overrideForPerfClass, int rotationOverride,
+ bool legacyClient = false);
+ status_t initialize(sp<CameraProviderManager> manager,
+ const std::string& monitorTags) override;
+ status_t disconnectClient(int clientUid) override;
+ status_t beginConfigure() override;
+ status_t getSharedStreamId(const OutputConfiguration &config, int *streamId) override;
+ status_t addSharedSurfaces(int streamId,
+ const std::vector<android::camera3::OutputStreamInfo> &outputInfo,
+ const std::vector<SurfaceHolder>& surfaces,
+ std::vector<int> *surfaceIds = nullptr) override;
+ status_t removeSharedSurfaces(int streamId,
+ const std::vector<size_t> &surfaceIds) override;
+ private:
+ static std::map<std::string, sp<AidlCamera3SharedDevice>> sSharedDevices;
+ static std::map<std::string, std::unordered_set<int>> sClientsUid;
+ AidlCamera3SharedDevice(
+ std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+ std::shared_ptr<AttributionAndPermissionUtils> attributionAndPermissionUtils,
+ const std::string& id, bool overrideForPerfClass, int rotationOverride,
+ bool legacyClient)
+ : AidlCamera3Device(cameraServiceProxyWrapper, attributionAndPermissionUtils, id,
+ overrideForPerfClass, rotationOverride, legacyClient) {}
+ std::vector<OutputConfiguration> getSharedOutputConfiguration();
+ std::vector<OutputConfiguration> mSharedOutputConfigurations;
+ std::vector<int> mSharedSurfaceIds;
+ std::vector<sp<Surface>> mSharedSurfaces;
+ std::vector<sp<Camera3SharedOutputStream>> mSharedStreams;
+ KeyedVector<int32_t, OutputConfiguration> mConfiguredOutputs;
+}; // class AidlCamera3SharedDevice
+}; // namespace android
+#endif
diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h
index 152002b..98a0dbb 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.h
@@ -86,6 +86,10 @@
mCaptureResultMetadataQueue = metadataQueue;
}
+ virtual binder::Status onClientSharedAccessPriorityChanged(bool /*primaryClient*/) {
+ return binder::Status::ok();
+ }
+
private:
// Wrapper struct so that parameters to onResultReceived callback may be
// sent through an AMessage.
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
index 78fca4e..b31ccc6 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
@@ -72,6 +72,10 @@
// empty implementation
return binder::Status::ok();
}
+ virtual binder::Status onCameraOpenedInSharedMode(const std::string& /*cameraId*/,
+ const std::string& /*clientPackageId*/, int32_t /*deviceId*/, bool /*primaryClient*/) {
+ return binder::Status::ok();
+ }
};
} // implementation
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 59e892f..9d140f2 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -135,7 +135,7 @@
binder::Status serviceRet = mAidlICameraService->connectDevice(
callbacks, cameraId, 0/*oomScoreOffset*/,
/*targetSdkVersion*/__ANDROID_API_FUTURE__, ROTATION_OVERRIDE_NONE,
- clientAttribution, /*devicePolicy*/0, /*out*/&deviceRemote);
+ clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, /*out*/&deviceRemote);
HStatus status = HStatus::NO_ERROR;
if (!serviceRet.isOk()) {
ALOGE("%s: Unable to connect to camera device", __FUNCTION__);
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
index 86e2c70..6c98837 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
@@ -749,6 +749,13 @@
// No op
return binder::Status::ok();
}
+
+ virtual binder::Status onCameraOpenedInSharedMode(const std::string& /*cameraId*/,
+ const std::string& /*clientPackageName*/, int32_t /*deviceId*/,
+ bool /*isPrimaryClient*/) {
+ // No op
+ return binder::Status::ok();
+ }
};
class TestCameraDeviceCallbacks : public hardware::camera2::BnCameraDeviceCallbacks {
@@ -789,6 +796,11 @@
virtual binder::Status onRequestQueueEmpty() {
return binder::Status::ok();
}
+
+ virtual binder::Status onClientSharedAccessPriorityChanged(bool /*isPrimaryClient*/) {
+ return binder::Status::ok();
+ }
+
};
class Camera2Fuzzer {
@@ -817,7 +829,7 @@
mCameraService->connectDevice(callbacks, s.cameraId,
0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT,
- clientAttribution, /*devicePolicy*/0, &device);
+ clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &device);
if (device == nullptr) {
continue;
}
diff --git a/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp b/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
index 50aeaca..ff58c4a 100644
--- a/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
@@ -77,6 +77,13 @@
// No op
return binder::Status::ok();
}
+
+ virtual binder::Status onCameraOpenedInSharedMode(const std::string& /*cameraId*/,
+ const std::string& /*clientPackageName*/, int32_t /*deviceId*/,
+ bool /*isPrimaryClient*/) {
+ // No op
+ return binder::Status::ok();
+ }
};
// Empty device callback.
@@ -118,6 +125,10 @@
virtual binder::Status onRequestQueueEmpty() {
return binder::Status::ok();
}
+
+ virtual binder::Status onClientSharedAccessPriorityChanged(bool /*isPrimaryClient*/) {
+ return binder::Status::ok();
+ }
};
// Override isCameraDisabled from the CameraServiceProxy with a flag.
@@ -242,7 +253,7 @@
sCameraService->connectDevice(callbacks, s.cameraId,
0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
hardware::ICameraService::ROTATION_OVERRIDE_NONE,
- clientAttribution, /*devicePolicy*/0, &device);
+ clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &device);
AutoDisconnectDevice autoDisconnect(device);
ASSERT_TRUE(!status.isOk()) << "connectDevice returned OK status";
ASSERT_EQ(status.serviceSpecificErrorCode(), hardware::ICameraService::ERROR_DISABLED)
@@ -257,7 +268,7 @@
sCameraService->connectDevice(callbacks, s.cameraId,
0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
hardware::ICameraService::ROTATION_OVERRIDE_NONE,
- clientAttribution, /*devicePolicy*/0, &device);
+ clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &device);
AutoDisconnectDevice autoDisconnect(device);
ASSERT_TRUE(status.isOk());
}
@@ -281,7 +292,7 @@
sCameraService->connectDevice(callbacks, s.cameraId,
0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
hardware::ICameraService::ROTATION_OVERRIDE_NONE,
- clientAttribution, /*devicePolicy*/0, &deviceA);
+ clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceA);
AutoDisconnectDevice autoDisconnectA(deviceA);
ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
" service specific error code " << status.serviceSpecificErrorCode();
@@ -289,7 +300,7 @@
sCameraService->connectDevice(callbacks, s.cameraId,
0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
hardware::ICameraService::ROTATION_OVERRIDE_NONE,
- clientAttribution, /*devicePolicy*/0, &deviceB);
+ clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceB);
AutoDisconnectDevice autoDisconnectB(deviceB);
ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
" service specific error code " << status.serviceSpecificErrorCode();
@@ -315,7 +326,7 @@
sCameraService->connectDevice(callbacks, s.cameraId,
0/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
hardware::ICameraService::ROTATION_OVERRIDE_NONE,
- clientAttribution, /*devicePolicy*/0, &deviceA);
+ clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceA);
AutoDisconnectDevice autoDisconnectA(deviceA);
ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
" service specific error code " << status.serviceSpecificErrorCode();
@@ -323,7 +334,7 @@
sCameraService->connectDevice(callbacks, s.cameraId,
1/*oomScoreDiff*/, /*targetSdkVersion*/__ANDROID_API_FUTURE__,
hardware::ICameraService::ROTATION_OVERRIDE_NONE,
- clientAttribution, /*devicePolicy*/0, &deviceB);
+ clientAttribution, /*devicePolicy*/0, /*sharedMode*/false, &deviceB);
AutoDisconnectDevice autoDisconnectB(deviceB);
ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
" service specific error code " << status.serviceSpecificErrorCode();
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index 074c84d..b2b8685 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -20,6 +20,7 @@
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <utils/Timers.h>
+#include <utils/Log.h>
#include <algorithm>
#include <utility>
@@ -27,6 +28,9 @@
#include <set>
#include <map>
#include <memory>
+#include <com_android_internal_camera_flags.h>
+
+namespace flags = com::android::internal::camera::flags;
namespace android {
namespace resource_policy {
@@ -142,10 +146,10 @@
public:
ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
- bool isVendorClient, int32_t oomScoreOffset);
+ bool isVendorClient, int32_t oomScoreOffset, bool sharedMode = false);
ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost, std::set<KEY>&& conflictingKeys,
int32_t score, int32_t ownerId, int32_t state, bool isVendorClient,
- int32_t oomScoreOffset);
+ int32_t oomScoreOffset, bool sharedMode = false);
~ClientDescriptor();
@@ -189,6 +193,11 @@
*/
void setPriority(const ClientPriority& priority);
+ /**
+ * Returns true when camera is opened in shared mode.
+ */
+ bool getSharedMode() const;
+
// This class is ordered by key
template<class K, class V>
friend bool operator < (const ClientDescriptor<K, V>& a, const ClientDescriptor<K, V>& b);
@@ -200,6 +209,7 @@
std::set<KEY> mConflicting;
ClientPriority mPriority;
int32_t mOwnerId;
+ bool mSharedMode;
}; // class ClientDescriptor
template<class K, class V>
@@ -210,18 +220,19 @@
template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
- bool isVendorClient, int32_t scoreOffset) :
+ bool isVendorClient, int32_t scoreOffset, bool sharedMode) :
mKey{key}, mValue{value}, mCost{cost}, mConflicting{conflictingKeys},
mPriority(score, state, isVendorClient, scoreOffset),
- mOwnerId{ownerId} {}
+ mOwnerId{ownerId}, mSharedMode{sharedMode} {}
template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost,
std::set<KEY>&& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
- bool isVendorClient, int32_t scoreOffset) :
+ bool isVendorClient, int32_t scoreOffset, bool sharedMode) :
mKey{std::forward<KEY>(key)}, mValue{std::forward<VALUE>(value)}, mCost{cost},
mConflicting{std::forward<std::set<KEY>>(conflictingKeys)},
- mPriority(score, state, isVendorClient, scoreOffset), mOwnerId{ownerId} {}
+ mPriority(score, state, isVendorClient, scoreOffset), mOwnerId{ownerId},
+ mSharedMode{sharedMode} {}
template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::~ClientDescriptor() {}
@@ -253,7 +264,14 @@
template<class KEY, class VALUE>
bool ClientDescriptor<KEY, VALUE>::isConflicting(const KEY& key) const {
- if (key == mKey) return true;
+ if (flags::camera_multi_client()) {
+ // In shared mode, there can be more than one client using the camera.
+ // Hence, having more than one client with the same key is not considered as
+ // conflicting.
+ if (!mSharedMode && key == mKey) return true;
+ } else {
+ if (key == mKey) return true;
+ }
for (const auto& x : mConflicting) {
if (key == x) return true;
}
@@ -266,6 +284,11 @@
}
template<class KEY, class VALUE>
+bool ClientDescriptor<KEY, VALUE>::getSharedMode() const {
+ return mSharedMode;
+}
+
+template<class KEY, class VALUE>
void ClientDescriptor<KEY, VALUE>::setPriority(const ClientPriority& priority) {
// We don't use the usual copy constructor here since we want to remember
// whether a client is a vendor client or not. This could have been wiped
@@ -349,14 +372,19 @@
void removeAll();
/**
- * Remove and return the ClientDescriptor with a given key.
+ * Remove all ClientDescriptors with a given key.
+ */
+ std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> removeAll(const KEY& key);
+
+ /**
+ * Remove and return the ClientDescriptors with a given key.
*/
std::shared_ptr<ClientDescriptor<KEY, VALUE>> remove(const KEY& key);
/**
* Remove the given ClientDescriptor.
*/
- void remove(const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value);
+ virtual void remove(const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value);
/**
* Return a vector of the ClientDescriptors that would be evicted by adding the given
@@ -395,6 +423,8 @@
*/
std::shared_ptr<ClientDescriptor<KEY, VALUE>> get(const KEY& key) const;
+ std::shared_ptr<ClientDescriptor<KEY, VALUE>> getPrimaryClient(const KEY& key) const;
+
/**
* Block until the given client is no longer in the active clients list, or the timeout
* occurred.
@@ -495,6 +525,8 @@
int32_t cost = client->getCost();
ClientPriority priority = client->getPriority();
int32_t owner = client->getOwnerId();
+ bool sharedMode = client->getSharedMode();
+
int64_t totalCost = getCurrentCostLocked() + cost;
@@ -520,9 +552,15 @@
int32_t curCost = i->getCost();
ClientPriority curPriority = i->getPriority();
int32_t curOwner = i->getOwnerId();
-
- bool conflicting = (curKey == key || i->isConflicting(key) ||
- client->isConflicting(curKey));
+ bool curSharedMode = i->getSharedMode();
+ bool conflicting;
+ if (flags::camera_multi_client()) {
+ conflicting = (((!sharedMode || !curSharedMode) && curKey == key)
+ || i->isConflicting(key) || client->isConflicting(curKey));
+ } else {
+ conflicting = (curKey == key || i->isConflicting(key) ||
+ client->isConflicting(curKey));
+ }
if (!returnIncompatibleClients) {
// Find evicted clients
@@ -669,6 +707,25 @@
}
template<class KEY, class VALUE, class LISTENER>
+std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::getPrimaryClient(
+ const KEY& key) const {
+ Mutex::Autolock lock(mLock);
+ if (flags::camera_multi_client()) {
+ for (const auto& i : mClients) {
+ bool sharedMode = i->getSharedMode();
+ bool primaryClient;
+ status_t ret = i->getValue()->isPrimaryClient(&primaryClient);
+ if (ret == OK) {
+ if ((i->getKey() == key) && sharedMode && primaryClient) {
+ return i;
+ }
+ }
+ }
+ }
+ return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
+}
+
+template<class KEY, class VALUE, class LISTENER>
void ClientManager<KEY, VALUE, LISTENER>::removeAll() {
Mutex::Autolock lock(mLock);
if (mListener != nullptr) {
@@ -681,6 +738,27 @@
}
template<class KEY, class VALUE, class LISTENER>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
+ ClientManager<KEY, VALUE, LISTENER>::removeAll(const KEY& key) {
+ Mutex::Autolock lock(mLock);
+ std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> clients;
+ if (flags::camera_multi_client()) {
+ for (auto it = mClients.begin(); it != mClients.end();)
+ {
+ if ((*it)->getKey() == key) {
+ it = mClients.erase(it);
+ if (mListener != nullptr) mListener->onClientRemoved(**it);
+ clients.push_back(*it);
+ } else {
+ ++it;
+ }
+ }
+ mRemovedCondition.broadcast();
+ }
+ return clients;
+}
+
+template<class KEY, class VALUE, class LISTENER>
std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::remove(
const KEY& key) {
Mutex::Autolock lock(mLock);