Merge "cameraserver: fix minor typo"
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 27ebb7a..8472562 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -37,6 +37,7 @@
"libui",
"libgui",
"libbinder",
+ "libbinder_ndk",
"libhidlbase",
"android.hardware.camera.common@1.0",
"android.hardware.camera.provider@2.4",
@@ -59,6 +60,6 @@
init_rc: ["cameraserver.rc"],
vintf_fragments: [
- "manifest_android.frameworks.cameraservice.service@2.2.xml",
+ "manifest_android.frameworks.cameraservice.service.xml",
],
}
diff --git a/camera/cameraserver/cameraserver.rc b/camera/cameraserver/cameraserver.rc
index 6a311f2..e307653 100644
--- a/camera/cameraserver/cameraserver.rc
+++ b/camera/cameraserver/cameraserver.rc
@@ -6,3 +6,4 @@
task_profiles CameraServiceCapacity MaxPerformance
rlimit rtprio 10 10
onrestart class_restart cameraWatchdog
+ interface aidl android.frameworks.cameraservice.service.ICameraService/default
diff --git a/camera/cameraserver/main_cameraserver.cpp b/camera/cameraserver/main_cameraserver.cpp
index cef8ef5..c494732 100644
--- a/camera/cameraserver/main_cameraserver.cpp
+++ b/camera/cameraserver/main_cameraserver.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include "CameraService.h"
+#include <android/binder_process.h>
#include <hidl/HidlTransportSupport.h>
using namespace android;
@@ -26,15 +27,21 @@
{
signal(SIGPIPE, SIG_IGN);
- // Set 5 threads for HIDL calls. Now cameraserver will serve HIDL calls in
- // addition to consuming them from the Camera HAL as well.
+ // Set 5 threads for HIDL calls. Now cameraserver will serve HIDL calls.
hardware::configureRpcThreadpool(5, /*willjoin*/ false);
+ // Set 5 threads for VNDK AIDL calls. Now cameraserver will serve
+ // VNDK AIDL calls in addition to consuming them from the Camera HAL as well.
+ ABinderProcess_setThreadPoolMaxThreadCount(5);
+
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
CameraService::instantiate();
ALOGI("ServiceManager: %p done instantiate", sm.get());
ProcessState::self()->startThreadPool();
+ ABinderProcess_startThreadPool();
+
IPCThreadState::self()->joinThreadPool();
+ ABinderProcess_joinThreadPool();
}
diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml
new file mode 100644
index 0000000..e892471
--- /dev/null
+++ b/camera/cameraserver/manifest_android.frameworks.cameraservice.service.xml
@@ -0,0 +1,20 @@
+<manifest version="1.0" type="framework">
+ <hal>
+ <name>android.frameworks.cameraservice.service</name>
+ <transport>hwbinder</transport>
+ <version>2.2</version>
+ <interface>
+ <name>ICameraService</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+
+ <hal format="aidl">
+ <name>android.frameworks.cameraservice.service</name>
+ <version>1</version>
+ <interface>
+ <name>ICameraService</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.2.xml b/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.2.xml
deleted file mode 100644
index eeafc91..0000000
--- a/camera/cameraserver/manifest_android.frameworks.cameraservice.service@2.2.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="framework">
- <hal>
- <name>android.frameworks.cameraservice.service</name>
- <transport>hwbinder</transport>
- <version>2.2</version>
- <interface>
- <name>ICameraService</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index fef873b..bfd02b3 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -141,6 +141,7 @@
],
shared_libs: [
+ "libbinder_ndk",
"libfmq",
"libhidlbase",
"libhardware",
@@ -151,15 +152,13 @@
"libcutils",
"libcamera_metadata",
"libmediandk",
- "android.frameworks.cameraservice.device@2.0",
- "android.frameworks.cameraservice.device@2.1",
- "android.frameworks.cameraservice.common@2.0",
- "android.frameworks.cameraservice.service@2.0",
- "android.frameworks.cameraservice.service@2.1",
- "android.frameworks.cameraservice.service@2.2",
+ "android.frameworks.cameraservice.common-V1-ndk",
+ "android.frameworks.cameraservice.device-V1-ndk",
+ "android.frameworks.cameraservice.service-V1-ndk",
],
static_libs: [
"android.hardware.camera.common@1.0-helper",
+ "libaidlcommonsupport",
"libarect",
],
// TODO: jchowdhary@, use header_libs instead b/131165718
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index 9c98778..65b8837 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -29,6 +29,7 @@
#include "impl/ACameraCaptureSession.h"
#include "impl/ACameraCaptureSession.inc"
+
#include "NdkCameraCaptureSession.inc"
using namespace android;
diff --git a/camera/ndk/NdkCameraDevice.cpp b/camera/ndk/NdkCameraDevice.cpp
index 691996b..8211671 100644
--- a/camera/ndk/NdkCameraDevice.cpp
+++ b/camera/ndk/NdkCameraDevice.cpp
@@ -22,18 +22,11 @@
#include <utils/Trace.h>
#include <camera/NdkCameraDevice.h>
+
#include "impl/ACameraCaptureSession.h"
using namespace android::acam;
-bool areWindowTypesEqual(ACameraWindowType *a, ACameraWindowType *b) {
-#ifdef __ANDROID_VNDK__
- return utils::isWindowNativeHandleEqual(a, b);
-#else
- return a == b;
-#endif
-}
-
EXPORT
camera_status_t ACameraDevice_close(ACameraDevice* device) {
ATRACE_CALL();
@@ -183,14 +176,15 @@
__FUNCTION__);
return ACAMERA_ERROR_INVALID_OPERATION;
}
- if (areWindowTypesEqual(out->mWindow, window)) {
+ if (out->isWindowEqual(window)) {
ALOGE("%s: Error trying to add the same window associated with the output configuration",
__FUNCTION__);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- auto insert = out->mSharedWindows.insert(window);
- camera_status_t ret = (insert.second) ? ACAMERA_OK : ACAMERA_ERROR_INVALID_PARAMETER;
+
+ bool insert = out->addSharedWindow(window);
+ camera_status_t ret = (insert) ? ACAMERA_OK : ACAMERA_ERROR_INVALID_PARAMETER;
return ret;
}
@@ -208,13 +202,13 @@
__FUNCTION__);
return ACAMERA_ERROR_INVALID_OPERATION;
}
- if (areWindowTypesEqual(out->mWindow, window)) {
+ if (out->isWindowEqual(window)) {
ALOGE("%s: Error trying to remove the same window associated with the output configuration",
__FUNCTION__);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- auto remove = out->mSharedWindows.erase(window);
+ auto remove = out->removeSharedWindow(window);
camera_status_t ret = (remove) ? ACAMERA_OK : ACAMERA_ERROR_INVALID_PARAMETER;
return ret;
}
diff --git a/camera/ndk/NdkCameraManager.cpp b/camera/ndk/NdkCameraManager.cpp
index 3d231a8..2de4a50 100644
--- a/camera/ndk/NdkCameraManager.cpp
+++ b/camera/ndk/NdkCameraManager.cpp
@@ -81,7 +81,7 @@
callback->onCameraAvailable, callback->onCameraUnavailable);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- CameraManagerGlobal::getInstance().registerAvailabilityCallback(callback);
+ CameraManagerGlobal::getInstance()->registerAvailabilityCallback(callback);
return ACAMERA_OK;
}
@@ -100,7 +100,7 @@
callback->onCameraAvailable, callback->onCameraUnavailable);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- CameraManagerGlobal::getInstance().unregisterAvailabilityCallback(callback);
+ CameraManagerGlobal::getInstance()->unregisterAvailabilityCallback(callback);
return ACAMERA_OK;
}
@@ -131,7 +131,7 @@
return ACAMERA_ERROR_INVALID_PARAMETER;
}
}
- CameraManagerGlobal::getInstance().registerExtendedAvailabilityCallback(callback);
+ CameraManagerGlobal::getInstance()->registerExtendedAvailabilityCallback(callback);
return ACAMERA_OK;
}
@@ -154,7 +154,7 @@
callback->onCameraAccessPrioritiesChanged);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- CameraManagerGlobal::getInstance().unregisterExtendedAvailabilityCallback(callback);
+ CameraManagerGlobal::getInstance()->unregisterExtendedAvailabilityCallback(callback);
return ACAMERA_OK;
}
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
index 68db233..110d47a 100644
--- a/camera/ndk/impl/ACameraCaptureSession.cpp
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -23,7 +23,11 @@
ACameraCaptureSession::~ACameraCaptureSession() {
ALOGV("~ACameraCaptureSession: %p notify device end of life", this);
+#ifdef __ANDROID_VNDK__
+ std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
if (dev != nullptr && !dev->isClosed()) {
dev->lockDeviceForSessionOps();
{
@@ -50,7 +54,11 @@
mClosedByApp = true;
}
+#ifdef __ANDROID_VNDK__
+ std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
if (dev != nullptr) {
dev->lockDeviceForSessionOps();
}
@@ -75,7 +83,11 @@
camera_status_t
ACameraCaptureSession::stopRepeating() {
+#ifdef __ANDROID_VNDK__
+ std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
if (dev == nullptr) {
ALOGE("Error: Device associated with session %p has been closed!", this);
return ACAMERA_ERROR_SESSION_CLOSED;
@@ -93,7 +105,11 @@
camera_status_t
ACameraCaptureSession::abortCaptures() {
+#ifdef __ANDROID_VNDK__
+ std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
if (dev == nullptr) {
ALOGE("Error: Device associated with session %p has been closed!", this);
return ACAMERA_ERROR_SESSION_CLOSED;
@@ -110,7 +126,11 @@
}
camera_status_t ACameraCaptureSession::updateOutputConfiguration(ACaptureSessionOutput *output) {
+#ifdef __ANDROID_VNDK__
+ std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
if (dev == nullptr) {
ALOGE("Error: Device associated with session %p has been closed!", this);
return ACAMERA_ERROR_SESSION_CLOSED;
@@ -129,7 +149,11 @@
ACameraDevice*
ACameraCaptureSession::getDevice() {
Mutex::Autolock _l(mSessionLock);
+#ifdef __ANDROID_VNDK__
+ std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
if (dev == nullptr) {
ALOGE("Error: Device associated with session %p has been closed!", this);
return nullptr;
@@ -143,6 +167,17 @@
mIsClosed = true;
}
+#ifdef __ANDROID_VNDK__
+std::shared_ptr<acam::CameraDevice>
+ACameraCaptureSession::getDevicePtr() {
+ std::shared_ptr<acam::CameraDevice> device = mDevice.lock();
+ if (device == nullptr || device->isClosed()) {
+ ALOGW("Device is closed but session %d is not notified", mId);
+ return nullptr;
+ }
+ return device;
+}
+#else
sp<acam::CameraDevice>
ACameraCaptureSession::getDeviceSp() {
sp<acam::CameraDevice> device = mDevice.promote();
@@ -152,5 +187,4 @@
}
return device;
}
-
-
+#endif
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
index 08a9226..cd65e8c 100644
--- a/camera/ndk/impl/ACameraCaptureSession.h
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -47,6 +47,21 @@
return mWindow > other.mWindow;
}
+ inline bool isWindowEqual(ACameraWindowType* window) const {
+ return mWindow == window;
+ }
+
+ // returns true if the window was successfully added, false otherwise.
+ inline bool addSharedWindow(ACameraWindowType* window) {
+ auto ret = mSharedWindows.insert(window);
+ return ret.second;
+ }
+
+ // returns the number of elements removed.
+ inline size_t removeSharedWindow(ACameraWindowType* window) {
+ return mSharedWindows.erase(window);
+ }
+
ACameraWindowType* mWindow;
std::set<ACameraWindowType *> mSharedWindows;
bool mIsShared;
@@ -65,6 +80,15 @@
*/
struct ACameraCaptureSession : public RefBase {
public:
+#ifdef __ANDROID_VNDK__
+ ACameraCaptureSession(
+ int id,
+ const ACaptureSessionOutputContainer* outputs,
+ const ACameraCaptureSession_stateCallbacks* cb,
+ std::weak_ptr<android::acam::CameraDevice> device) :
+ mId(id), mOutput(*outputs), mUserSessionCallback(*cb),
+ mDevice(std::move(device)) {}
+#else
ACameraCaptureSession(
int id,
const ACaptureSessionOutputContainer* outputs,
@@ -72,6 +96,7 @@
android::acam::CameraDevice* device) :
mId(id), mOutput(*outputs), mUserSessionCallback(*cb),
mDevice(device) {}
+#endif
// This can be called in app calling close() or after some app callback is finished
// Make sure the caller does not hold device or session lock!
@@ -114,12 +139,21 @@
// or a new session is replacing this session.
void closeByDevice();
+#ifdef __ANDROID_VNDK__
+ std::shared_ptr<android::acam::CameraDevice> getDevicePtr();
+#else
sp<android::acam::CameraDevice> getDeviceSp();
+#endif
const int mId;
const ACaptureSessionOutputContainer mOutput;
const ACameraCaptureSession_stateCallbacks mUserSessionCallback;
+#ifdef __ANDROID_VNDK__
+ const std::weak_ptr<android::acam::CameraDevice> mDevice;
+#else
const wp<android::acam::CameraDevice> mDevice;
+#endif
+
bool mIsClosed = false;
bool mClosedByApp = false;
Mutex mSessionLock;
diff --git a/camera/ndk/impl/ACameraCaptureSession.inc b/camera/ndk/impl/ACameraCaptureSession.inc
index 86bf8a5..da535f8 100644
--- a/camera/ndk/impl/ACameraCaptureSession.inc
+++ b/camera/ndk/impl/ACameraCaptureSession.inc
@@ -15,9 +15,8 @@
*/
#include "ACameraCaptureSession.h"
-
#ifdef __ANDROID_VNDK__
-#include "ndk_vendor/impl/ACameraDeviceVendor.inc"
+#include <ndk_vendor/impl/ACameraDeviceVendor.inc>
#else
#include "ACameraDevice.inc"
#endif
@@ -30,7 +29,11 @@
/*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId) {
+#ifdef __ANDROID_VNDK__
+ std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
if (dev == nullptr) {
ALOGE("Error: Device associated with session %p has been closed!", this);
return ACAMERA_ERROR_SESSION_CLOSED;
@@ -52,7 +55,11 @@
/*optional*/T* cbs,
int numRequests, ACaptureRequest** requests,
/*optional*/int* captureSequenceId) {
+#ifdef __ANDROID_VNDK__
+ std::shared_ptr<acam::CameraDevice> dev = getDevicePtr();
+#else
sp<acam::CameraDevice> dev = getDeviceSp();
+#endif
if (dev == nullptr) {
ALOGE("Error: Device associated with session %p has been closed!", this);
return ACAMERA_ERROR_SESSION_CLOSED;
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 7997768..536055b 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -1412,7 +1412,6 @@
while (it != mSequenceLastFrameNumberMap.end()) {
int sequenceId = it->first;
int64_t lastFrameNumber = it->second.lastFrameNumber;
- bool hasCallback = true;
if (mRemote == nullptr) {
ALOGW("Camera %s closed while checking sequence complete", getId());
@@ -1425,7 +1424,6 @@
// This should not happen because we always register callback (with nullptr inside)
if (mSequenceCallbackMap.count(sequenceId) == 0) {
ALOGW("No callback found for sequenceId %d", sequenceId);
- hasCallback = false;
}
if (lastFrameNumber <= completedFrameNumber) {
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 23d90cc..9dc262f 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -38,17 +38,16 @@
const char* CameraManagerGlobal::kContextKey = "CallbackContext";
const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
Mutex CameraManagerGlobal::sLock;
-CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
+wp<CameraManagerGlobal> CameraManagerGlobal::sInstance = nullptr;
-CameraManagerGlobal&
-CameraManagerGlobal::getInstance() {
+sp<CameraManagerGlobal> CameraManagerGlobal::getInstance() {
Mutex::Autolock _l(sLock);
- CameraManagerGlobal* instance = sInstance;
+ sp<CameraManagerGlobal> instance = sInstance.promote();
if (instance == nullptr) {
instance = new CameraManagerGlobal();
sInstance = instance;
}
- return *instance;
+ return instance;
}
CameraManagerGlobal::~CameraManagerGlobal() {
@@ -637,7 +636,7 @@
Mutex::Autolock _l(mLock);
std::vector<String8> idList;
- CameraManagerGlobal::getInstance().getCameraIdList(&idList);
+ CameraManagerGlobal::getInstance()->getCameraIdList(&idList);
int numCameras = idList.size();
ACameraIdList *out = new ACameraIdList;
@@ -687,7 +686,7 @@
const char* cameraIdStr, sp<ACameraMetadata>* characteristics) {
Mutex::Autolock _l(mLock);
- sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+ sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
if (cs == nullptr) {
ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
@@ -733,7 +732,7 @@
ACameraDevice* device = new ACameraDevice(cameraId, callback, chars);
- sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+ sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
if (cs == nullptr) {
ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
delete device;
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index d53d809..0dd79da 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -46,7 +46,7 @@
*/
class CameraManagerGlobal final : public RefBase {
public:
- static CameraManagerGlobal& getInstance();
+ static sp<CameraManagerGlobal> getInstance();
sp<hardware::ICameraService> getCameraService();
void registerAvailabilityCallback(
@@ -257,7 +257,7 @@
// For the singleton instance
static Mutex sLock;
- static CameraManagerGlobal* sInstance;
+ static wp<CameraManagerGlobal> sInstance;
CameraManagerGlobal() {};
~CameraManagerGlobal();
};
@@ -271,7 +271,7 @@
*/
struct ACameraManager {
ACameraManager() :
- mGlobalManager(&(android::acam::CameraManagerGlobal::getInstance())) {}
+ mGlobalManager(android::acam::CameraManagerGlobal::getInstance()) {}
~ACameraManager();
camera_status_t getCameraIdList(ACameraIdList** cameraIdList);
static void deleteCameraIdList(ACameraIdList* cameraIdList);
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 152b786..6f97770 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -3740,9 +3740,9 @@
* <p>Output streams use this rectangle to produce their output, cropping to a smaller region
* if necessary to maintain the stream's aspect ratio, then scaling the sensor input to
* match the output's configured resolution.</p>
- * <p>The crop region is applied after the RAW to other color space (e.g. YUV)
- * conversion. Since raw streams (e.g. RAW16) don't have the conversion stage, they are not
- * croppable. The crop region will be ignored by raw streams.</p>
+ * <p>The crop region is usually applied after the RAW to other color space (e.g. YUV)
+ * conversion. As a result RAW streams are not croppable unless supported by the
+ * camera device. See ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES#CROPPED_RAW for details.</p>
* <p>For non-raw streams, any additional per-stream cropping will be done to maximize the
* final pixel area of the stream.</p>
* <p>For example, if the crop region is set to a 4:3 aspect ratio, then 4:3 streams will use
@@ -3833,6 +3833,7 @@
* @see ACAMERA_CONTROL_ZOOM_RATIO
* @see ACAMERA_DISTORTION_CORRECTION_MODE
* @see ACAMERA_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
+ * @see ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES
* @see ACAMERA_SCALER_CROPPING_TYPE
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
@@ -4488,6 +4489,59 @@
*/
ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES = // int64[n] (acamera_metadata_enum_android_scaler_available_stream_use_cases_t)
ACAMERA_SCALER_START + 25,
+ /**
+ * <p>The region of the sensor that corresponds to the RAW read out for this
+ * capture when the stream use case of a RAW stream is set to CROPPED_RAW.</p>
+ *
+ * <p>Type: int32[4]</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraCaptureSession_captureCallback_result callbacks</li>
+ * </ul></p>
+ *
+ * <p>The coordinate system follows that of ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE.</p>
+ * <p>This CaptureResult key will be set when the corresponding CaptureRequest has a RAW target
+ * with stream use case set to
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW">CameraMetadata#SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW</a>,
+ * otherwise it will be {@code null}.
+ * The value of this key specifies the region of the sensor used for the RAW capture and can
+ * be used to calculate the corresponding field of view of RAW streams.
+ * This field of view will always be >= field of view for (processed) non-RAW streams for the
+ * capture. Note: The region specified may not necessarily be centered.</p>
+ * <p>For example: Assume a camera device has a pre correction active array size of
+ * {@code {0, 0, 1500, 2000}}. If the RAW_CROP_REGION is {@code {500, 375, 1500, 1125}}, that
+ * corresponds to a centered crop of 1/4th of the full field of view RAW stream.</p>
+ * <p>The metadata keys which describe properties of RAW frames:</p>
+ * <ul>
+ * <li>ACAMERA_STATISTICS_HOT_PIXEL_MAP</li>
+ * <li>android.statistics.lensShadingCorrectionMap</li>
+ * <li>ACAMERA_LENS_DISTORTION</li>
+ * <li>ACAMERA_LENS_POSE_TRANSLATION</li>
+ * <li>ACAMERA_LENS_POSE_ROTATION</li>
+ * <li>ACAMERA_LENS_DISTORTION</li>
+ * <li>ACAMERA_LENS_INTRINSIC_CALIBRATION</li>
+ * </ul>
+ * <p>should be interpreted in the effective after raw crop field-of-view coordinate system.
+ * In this coordinate system,
+ * {preCorrectionActiveArraySize.left, preCorrectionActiveArraySize.top} corresponds to the
+ * the top left corner of the cropped RAW frame and
+ * {preCorrectionActiveArraySize.right, preCorrectionActiveArraySize.bottom} corresponds to
+ * the bottom right corner. Client applications must use the values of the keys
+ * in the CaptureResult metadata if present.</p>
+ * <p>Crop regions (android.scaler.CropRegion), AE/AWB/AF regions and face coordinates still
+ * use the ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE coordinate system as usual.</p>
+ *
+ * @see ACAMERA_LENS_DISTORTION
+ * @see ACAMERA_LENS_INTRINSIC_CALIBRATION
+ * @see ACAMERA_LENS_POSE_ROTATION
+ * @see ACAMERA_LENS_POSE_TRANSLATION
+ * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
+ * @see ACAMERA_STATISTICS_HOT_PIXEL_MAP
+ */
+ ACAMERA_SCALER_RAW_CROP_REGION = // int32[4]
+ ACAMERA_SCALER_START + 26,
ACAMERA_SCALER_END,
/**
@@ -10207,6 +10261,30 @@
*/
ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL = 0x5,
+ /**
+ * <p>Cropped RAW stream when the client chooses to crop the field of view.</p>
+ * <p>Certain types of image sensors can run in binned modes in order to improve signal to
+ * noise ratio while capturing frames. However, at certain zoom levels and / or when
+ * other scene conditions are deemed fit, the camera sub-system may choose to un-bin and
+ * remosaic the sensor's output. This results in a RAW frame which is cropped in field
+ * of view and yet has the same number of pixels as full field of view RAW, thereby
+ * improving image detail.</p>
+ * <p>The resultant field of view of the RAW stream will be greater than or equal to
+ * croppable non-RAW streams. The effective crop region for this RAW stream will be
+ * reflected in the CaptureResult key ACAMERA_SCALER_RAW_CROP_REGION.</p>
+ * <p>If this stream use case is set on a non-RAW stream, i.e. not one of :</p>
+ * <ul>
+ * <li>{@link AIMAGE_FORMAT_RAW16 RAW_SENSOR}</li>
+ * <li>{@link AIMAGE_FORMAT_RAW10 RAW10}</li>
+ * <li>{@link AIMAGE_FORMAT_RAW12 RAW12}</li>
+ * </ul>
+ * <p>session configuration is not guaranteed to succeed.</p>
+ * <p>This stream use case may not be supported on some devices.</p>
+ *
+ * @see ACAMERA_SCALER_RAW_CROP_REGION
+ */
+ ACAMERA_SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW = 0x6,
+
} acamera_metadata_enum_android_scaler_available_stream_use_cases_t;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
index 5a1af79..45098c3 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraCaptureSessionVendor.h
@@ -14,9 +14,14 @@
* limitations under the License.
*/
-#include <string>
#include "utils.h"
+#include <android/binder_auto_utils.h>
+#include <string>
+#include <set>
+
+using ::android::acam::utils::native_handle_ptr_wrapper;
+
struct ACaptureSessionOutput {
explicit ACaptureSessionOutput(const native_handle_t* window, bool isShared = false,
const char* physicalCameraId = "") :
@@ -38,8 +43,23 @@
return mWindow > other.mWindow;
}
- android::acam::utils::native_handle_ptr_wrapper mWindow;
- std::set<android::acam::utils::native_handle_ptr_wrapper> mSharedWindows;
+ inline bool isWindowEqual(ACameraWindowType* window) const {
+ return mWindow == native_handle_ptr_wrapper(window);
+ }
+
+ // returns true if the window was successfully added, false otherwise.
+ inline bool addSharedWindow(ACameraWindowType* window) {
+ auto ret = mSharedWindows.insert(window);
+ return ret.second;
+ }
+
+ // returns the number of elements removed.
+ inline size_t removeSharedWindow(ACameraWindowType* window) {
+ return mSharedWindows.erase(window);
+ }
+
+ native_handle_ptr_wrapper mWindow;
+ std::set<native_handle_ptr_wrapper> mSharedWindows;
bool mIsShared;
int mRotation = CAMERA3_STREAM_ROTATION_0;
std::string mPhysicalCameraId;
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 0a57590..96df7db 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -17,27 +17,34 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ACameraDeviceVendor"
-#include <vector>
-#include <inttypes.h>
-#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
-#include <android/frameworks/cameraservice/device/2.0/types.h>
-#include <CameraMetadata.h>
-
-#include "ndk_vendor/impl/ACameraDevice.h"
#include "ACameraCaptureSession.h"
#include "ACameraMetadata.h"
#include "ACaptureRequest.h"
+#include "ndk_vendor/impl/ACameraDevice.h"
#include "utils.h"
+#include <CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/device/CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/device/OutputConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/SessionConfiguration.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <inttypes.h>
+#include <map>
+#include <utility>
+#include <vector>
-#define CHECK_TRANSACTION_AND_RET(remoteRet, status, callName) \
- if (!remoteRet.isOk()) { \
- ALOGE("%s: Transaction error during %s call %s", __FUNCTION__, callName, \
- remoteRet.description().c_str()); \
- return ACAMERA_ERROR_UNKNOWN; \
- } \
- if (status != Status::NO_ERROR) { \
- ALOGE("%s: %s call failed", __FUNCTION__, callName); \
- return utils::convertFromHidl(status); \
+#define CHECK_TRANSACTION_AND_RET(ret, callName) \
+ if (!remoteRet.isOk()) { \
+ if (remoteRet.getExceptionCode() != EX_SERVICE_SPECIFIC) { \
+ ALOGE("%s: Transaction error during %s call %d", __FUNCTION__, callName, \
+ ret.getExceptionCode()); \
+ return ACAMERA_ERROR_UNKNOWN; \
+ } else { \
+ Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError()); \
+ std::string errorMsg = \
+ aidl::android::frameworks::cameraservice::common::toString(errStatus); \
+ ALOGE("%s: %s call failed: %s", __FUNCTION__, callName, errorMsg.c_str()); \
+ return utils::convertFromAidl(errStatus); \
+ } \
}
using namespace android;
@@ -49,10 +56,10 @@
namespace android {
namespace acam {
-using HCameraMetadata = frameworks::cameraservice::device::V2_0::CameraMetadata;
-using OutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration;
-using SessionConfiguration = frameworks::cameraservice::device::V2_0::SessionConfiguration;
-using hardware::Void;
+using AidlCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using ::aidl::android::frameworks::cameraservice::device::OutputConfiguration;
+using ::aidl::android::frameworks::cameraservice::device::SessionConfiguration;
+using ::ndk::ScopedAStatus;
// Static member definitions
const char* CameraDevice::kContextKey = "Context";
@@ -81,7 +88,6 @@
mCameraId(id),
mAppCallbacks(*cb),
mChars(std::move(chars)),
- mServiceCallback(new ServiceCallback(this)),
mWrapper(wrapper),
mInError(false),
mError(ACAMERA_OK),
@@ -125,8 +131,11 @@
CameraDevice::~CameraDevice() { }
-void
-CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
+void CameraDevice::init() {
+ mServiceCallback = ndk::SharedRefBase::make<ServiceCallback>(weak_from_this());
+}
+
+void CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
msg->post();
msg.clear();
sp<AMessage> cleanupMsg = new AMessage(kWhatCleanUpSessions, mHandler);
@@ -134,8 +143,7 @@
}
// TODO: cached created request?
-camera_status_t
-CameraDevice::createCaptureRequest(
+camera_status_t CameraDevice::createCaptureRequest(
ACameraDevice_request_template templateId,
const ACameraIdList* physicalCameraIdList,
ACaptureRequest** request) const {
@@ -147,20 +155,16 @@
if (mRemote == nullptr) {
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
- CameraMetadata rawRequest;
- Status status = Status::UNKNOWN_ERROR;
- auto remoteRet = mRemote->createDefaultRequest(
- utils::convertToHidl(templateId),
- [&status, &rawRequest](auto s, const hidl_vec<uint8_t> &metadata) {
- status = s;
- if (status == Status::NO_ERROR && utils::convertFromHidlCloned(metadata, &rawRequest)) {
- } else {
- ALOGE("%s: Couldn't create default request", __FUNCTION__);
- }
- });
- CHECK_TRANSACTION_AND_RET(remoteRet, status, "createDefaultRequest()")
+
+ AidlCameraMetadata aidlMetadata;
+ ScopedAStatus remoteRet = mRemote->createDefaultRequest(
+ utils::convertToAidl(templateId), &aidlMetadata);
+ CHECK_TRANSACTION_AND_RET(remoteRet, "createDefaultRequest()")
+
+ camera_metadata_t* rawRequest;
+ utils::cloneFromAidl(aidlMetadata, &rawRequest);
ACaptureRequest* outReq = new ACaptureRequest();
- outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
+ outReq->settings = new ACameraMetadata(rawRequest, ACameraMetadata::ACM_REQUEST);
if (physicalCameraIdList != nullptr) {
for (auto i = 0; i < physicalCameraIdList->numCameras; i++) {
outReq->physicalSettings.emplace(physicalCameraIdList->cameraIds[i],
@@ -172,9 +176,8 @@
return ACAMERA_OK;
}
-camera_status_t
-CameraDevice::createCaptureSession(
- const ACaptureSessionOutputContainer* outputs,
+camera_status_t CameraDevice::createCaptureSession(
+ const ACaptureSessionOutputContainer* outputs,
const ACaptureRequest* sessionParameters,
const ACameraCaptureSession_stateCallbacks* callbacks,
/*out*/ACameraCaptureSession** session) {
@@ -199,7 +202,7 @@
}
ACameraCaptureSession* newSession = new ACameraCaptureSession(
- mNextSessionId++, outputs, callbacks, this);
+ mNextSessionId++, outputs, callbacks, weak_from_this());
// set new session as current session
newSession->incStrong((void *) ACameraDevice_createCaptureSession);
@@ -225,41 +228,39 @@
sessionConfig.outputStreams.resize(sessionOutputContainer->mOutputs.size());
size_t index = 0;
for (const auto& output : sessionOutputContainer->mOutputs) {
- sessionConfig.outputStreams[index].rotation = utils::convertToHidl(output.mRotation);
- sessionConfig.outputStreams[index].windowGroupId = -1;
- sessionConfig.outputStreams[index].windowHandles.resize(output.mSharedWindows.size() + 1);
- sessionConfig.outputStreams[index].windowHandles[0] = output.mWindow;
- sessionConfig.outputStreams[index].physicalCameraId = output.mPhysicalCameraId;
+ OutputConfiguration& outputStream = sessionConfig.outputStreams[index];
+ outputStream.rotation = utils::convertToAidl(output.mRotation);
+ outputStream.windowGroupId = -1;
+ outputStream.windowHandles.resize(output.mSharedWindows.size() + 1);
+ outputStream.windowHandles[0] = std::move(dupToAidl(output.mWindow));
+ outputStream.physicalCameraId = output.mPhysicalCameraId;
index++;
}
bool configSupported = false;
- Status status = Status::UNKNOWN_ERROR;
- auto remoteRet = mRemote->isSessionConfigurationSupported(sessionConfig,
- [&status, &configSupported](auto s, auto supported) {
- status = s;
- configSupported = supported;
- });
-
- CHECK_TRANSACTION_AND_RET(remoteRet, status, "isSessionConfigurationSupported()");
+ ScopedAStatus remoteRet = mRemote->isSessionConfigurationSupported(
+ sessionConfig, &configSupported);
+ CHECK_TRANSACTION_AND_RET(remoteRet, "isSessionConfigurationSupported()")
return configSupported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
}
static void addMetadataToPhysicalCameraSettings(const CameraMetadata *metadata,
const std::string &cameraId, PhysicalCameraSettings *physicalCameraSettings) {
- CameraMetadata metadataCopy = *metadata;
- camera_metadata_t *camera_metadata = metadataCopy.release();
- HCameraMetadata hCameraMetadata;
- utils::convertToHidl(camera_metadata, &hCameraMetadata, /*shouldOwn*/ true);
- physicalCameraSettings->settings.metadata(std::move(hCameraMetadata));
+ const camera_metadata_t* cameraMetadata = metadata->getAndLock();
+ AidlCameraMetadata aidlCameraMetadata;
+ utils::convertToAidl(cameraMetadata, &aidlCameraMetadata);
+ metadata->unlock(cameraMetadata);
+ physicalCameraSettings->settings.set<CaptureMetadataInfo::metadata>(
+ std::move(aidlCameraMetadata));
physicalCameraSettings->id = cameraId;
}
void CameraDevice::addRequestSettingsMetadata(ACaptureRequest *aCaptureRequest,
sp<CaptureRequest> &req) {
req->mPhysicalCameraSettings.resize(1 + aCaptureRequest->physicalSettings.size());
- addMetadataToPhysicalCameraSettings(&(aCaptureRequest->settings->getInternalData()), getId(),
- &(req->mPhysicalCameraSettings[0]));
+ addMetadataToPhysicalCameraSettings(
+ &(aCaptureRequest->settings->getInternalData()),
+ getId(),&(req->mPhysicalCameraSettings[0]));
size_t i = 1;
for (auto &physicalSetting : aCaptureRequest->physicalSettings) {
addMetadataToPhysicalCameraSettings(&(physicalSetting.second->getInternalData()),
@@ -285,7 +286,7 @@
int32_t streamId = -1;
for (auto& kvPair : mConfiguredOutputs) {
- if (utils::isWindowNativeHandleEqual(kvPair.second.first, output->mWindow)) {
+ if (kvPair.second.first == output->mWindow) {
streamId = kvPair.first;
break;
}
@@ -295,56 +296,59 @@
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- OutputConfigurationWrapper outConfigW;
- OutputConfiguration &outConfig = outConfigW.mOutputConfiguration;
- outConfig.rotation = utils::convertToHidl(output->mRotation);
+ OutputConfiguration outConfig;
+ outConfig.rotation = utils::convertToAidl(output->mRotation);
outConfig.windowHandles.resize(output->mSharedWindows.size() + 1);
- outConfig.windowHandles[0] = output->mWindow;
+ outConfig.windowHandles[0] = std::move(dupToAidl(output->mWindow));
outConfig.physicalCameraId = output->mPhysicalCameraId;
int i = 1;
for (auto& anw : output->mSharedWindows) {
- outConfig.windowHandles[i++] = anw;
+ outConfig.windowHandles[i++] = std::move(dupToAidl(anw));
}
- auto remoteRet = mRemote->updateOutputConfiguration(streamId, outConfig);
+ auto remoteRet = mRemote->updateOutputConfiguration(streamId,
+ outConfig);
+
if (!remoteRet.isOk()) {
- ALOGE("%s: Transaction error in updating OutputConfiguration: %s", __FUNCTION__,
- remoteRet.description().c_str());
- return ACAMERA_ERROR_UNKNOWN;
+ if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ Status st = static_cast<Status>(remoteRet.getServiceSpecificError());
+ switch (st) {
+ case Status::NO_ERROR:
+ break;
+ case Status::INVALID_OPERATION:
+ ALOGE("Camera device %s invalid operation", getId());
+ return ACAMERA_ERROR_INVALID_OPERATION;
+ case Status::ALREADY_EXISTS:
+ ALOGE("Camera device %s output surface already exists", getId());
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ case Status::ILLEGAL_ARGUMENT:
+ ALOGE("Camera device %s invalid input argument", getId());
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ default:
+ ALOGE("Camera device %s failed to add shared output", getId());
+ return ACAMERA_ERROR_UNKNOWN;
+ }
+ } else {
+ ALOGE("%s: Transaction error in updating OutputConfiguration: %d", __FUNCTION__,
+ remoteRet.getExceptionCode());
+ return ACAMERA_ERROR_UNKNOWN;
+ }
}
- switch (remoteRet) {
- case Status::NO_ERROR:
- break;
- case Status::INVALID_OPERATION:
- ALOGE("Camera device %s invalid operation", getId());
- return ACAMERA_ERROR_INVALID_OPERATION;
- case Status::ALREADY_EXISTS:
- ALOGE("Camera device %s output surface already exists", getId());
- return ACAMERA_ERROR_INVALID_PARAMETER;
- case Status::ILLEGAL_ARGUMENT:
- ALOGE("Camera device %s invalid input argument", getId());
- return ACAMERA_ERROR_INVALID_PARAMETER;
- default:
- ALOGE("Camera device %s failed to add shared output", getId());
- return ACAMERA_ERROR_UNKNOWN;
- }
-
- mConfiguredOutputs[streamId] =
- std::move(std::make_pair(std::move(output->mWindow), std::move(outConfigW)));
-
+ mConfiguredOutputs[streamId] = std::make_pair(output->mWindow,
+ std::move(outConfig));
return ACAMERA_OK;
}
-camera_status_t
-CameraDevice::allocateCaptureRequestLocked(
+camera_status_t CameraDevice::allocateCaptureRequestLocked(
const ACaptureRequest* request, /*out*/sp<CaptureRequest> &outReq) {
sp<CaptureRequest> req(new CaptureRequest());
req->mCaptureRequest.physicalCameraSettings.resize(1 + request->physicalSettings.size());
size_t index = 0;
allocateOneCaptureRequestMetadata(
- req->mCaptureRequest.physicalCameraSettings[index++], mCameraId, request->settings);
+ req->mCaptureRequest.physicalCameraSettings[index++],
+ mCameraId, request->settings);
for (auto& physicalEntry : request->physicalSettings) {
allocateOneCaptureRequestMetadata(
@@ -354,19 +358,20 @@
std::vector<int32_t> requestStreamIdxList;
std::vector<int32_t> requestSurfaceIdxList;
- for (auto outputTarget : request->targets->mOutputs) {
- const native_handle_t* anw = outputTarget.mWindow;
+
+ for (auto& outputTarget : request->targets->mOutputs) {
+ native_handle_ptr_wrapper anw = outputTarget.mWindow;
bool found = false;
req->mSurfaceList.push_back(anw);
// lookup stream/surface ID
for (const auto& kvPair : mConfiguredOutputs) {
int streamId = kvPair.first;
- const OutputConfigurationWrapper& outConfig = kvPair.second.second;
- const auto& windowHandles = outConfig.mOutputConfiguration.windowHandles;
+ const OutputConfiguration& outConfig = kvPair.second.second;
+ const auto& windowHandles = outConfig.windowHandles;
for (int surfaceId = 0; surfaceId < (int) windowHandles.size(); surfaceId++) {
- // If two native handles are equivalent, so are their surfaces.
- if (utils::isWindowNativeHandleEqual(windowHandles[surfaceId].getNativeHandle(),
- anw)) {
+ // If two window handles point to the same native window,
+ // they have the same surfaces.
+ if (utils::isWindowNativeHandleEqual(anw, windowHandles[surfaceId])) {
found = true;
requestStreamIdxList.push_back(streamId);
requestSurfaceIdxList.push_back(surfaceId);
@@ -378,7 +383,7 @@
}
}
if (!found) {
- ALOGE("Unconfigured output target %p in capture request!", anw);
+ ALOGE("Unconfigured output target %p in capture request!", anw.mWindow);
return ACAMERA_ERROR_INVALID_PARAMETER;
}
}
@@ -395,54 +400,57 @@
PhysicalCameraSettings& cameraSettings,
const std::string& id, const sp<ACameraMetadata>& metadata) {
cameraSettings.id = id;
- // TODO: Do we really need to copy the metadata here ?
- CameraMetadata metadataCopy = metadata->getInternalData();
- camera_metadata_t *cameraMetadata = metadataCopy.release();
- HCameraMetadata hCameraMetadata;
- utils::convertToHidl(cameraMetadata, &hCameraMetadata, true);
- if (metadata != nullptr) {
- if (hCameraMetadata.data() != nullptr &&
- mCaptureRequestMetadataQueue != nullptr &&
- mCaptureRequestMetadataQueue->write(
- reinterpret_cast<const uint8_t *>(hCameraMetadata.data()),
- hCameraMetadata.size())) {
- // The metadata field of the union would've been destructued, so no need
- // to re-size it.
- cameraSettings.settings.fmqMetadataSize(hCameraMetadata.size());
- } else {
- ALOGE("Fmq write capture result failed, falling back to hwbinder");
- cameraSettings.settings.metadata(std::move(hCameraMetadata));
- }
+
+ if (metadata == nullptr) {
+ return;
+ }
+
+ const camera_metadata_t* cameraMetadata = metadata->getInternalData().getAndLock();
+ AidlCameraMetadata aidlCameraMetadata;
+ utils::convertToAidl(cameraMetadata, &aidlCameraMetadata);
+ metadata->getInternalData().unlock(cameraMetadata);
+
+ if (aidlCameraMetadata.metadata.data() != nullptr &&
+ mCaptureRequestMetadataQueue != nullptr &&
+ mCaptureRequestMetadataQueue->write(
+ reinterpret_cast<const int8_t*>(aidlCameraMetadata.metadata.data()),
+ aidlCameraMetadata.metadata.size())) {
+ cameraSettings.settings.set<CaptureMetadataInfo::fmqMetadataSize>(
+ aidlCameraMetadata.metadata.size());
+ } else {
+ ALOGE("Fmq write capture result failed, falling back to hwbinder");
+ cameraSettings.settings.set<CaptureMetadataInfo::metadata>(std::move(aidlCameraMetadata));
}
}
-ACaptureRequest*
-CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req, const char* deviceId) {
+ACaptureRequest* CameraDevice::allocateACaptureRequest(sp<CaptureRequest>& req,
+ const char* deviceId) {
ACaptureRequest* pRequest = new ACaptureRequest();
for (size_t i = 0; i < req->mPhysicalCameraSettings.size(); i++) {
const std::string& id = req->mPhysicalCameraSettings[i].id;
- CameraMetadata clone;
- utils::convertFromHidlCloned(req->mPhysicalCameraSettings[i].settings.metadata(), &clone);
- camera_metadata_t *clonep = clone.release();
+ camera_metadata_t* clone;
+ AidlCameraMetadata& aidlCameraMetadata = req->mPhysicalCameraSettings[i].settings
+ .get<CaptureMetadataInfo::metadata>();
+ utils::cloneFromAidl(aidlCameraMetadata, &clone);
+
if (id == deviceId) {
- pRequest->settings = new ACameraMetadata(clonep, ACameraMetadata::ACM_REQUEST);
+ pRequest->settings = new ACameraMetadata(clone, ACameraMetadata::ACM_REQUEST);
} else {
pRequest->physicalSettings[req->mPhysicalCameraSettings[i].id] =
- new ACameraMetadata(clonep, ACameraMetadata::ACM_REQUEST);
+ new ACameraMetadata(clone, ACameraMetadata::ACM_REQUEST);
}
}
pRequest->targets = new ACameraOutputTargets();
for (size_t i = 0; i < req->mSurfaceList.size(); i++) {
- const native_handle_t* anw = req->mSurfaceList[i];
+ native_handle_ptr_wrapper anw = req->mSurfaceList[i];
ACameraOutputTarget outputTarget(anw);
- pRequest->targets->mOutputs.insert(outputTarget);
+ pRequest->targets->mOutputs.insert(std::move(outputTarget));
}
return pRequest;
}
-void
-CameraDevice::freeACaptureRequest(ACaptureRequest* req) {
+void CameraDevice::freeACaptureRequest(ACaptureRequest* req) {
if (req == nullptr) {
return;
}
@@ -459,7 +467,7 @@
}
if (mCurrentSession != session) {
- // Session has been replaced by other seesion or device is closed
+ // Session has been replaced by other session or device is closed
return;
}
mCurrentSession = nullptr;
@@ -471,8 +479,8 @@
return;
}
- // No new session, unconfigure now
- // Note: The unconfiguration of session won't be accounted for session
+ // No new session, un-configure now
+ // Note: The un-configuration of session won't be accounted for session
// latency because a stream configuration with 0 streams won't ever become
// active.
nsecs_t startTimeNs = systemTime();
@@ -494,8 +502,8 @@
ALOGD("%s: binder disconnect reached", __FUNCTION__);
auto ret = mRemote->disconnect();
if (!ret.isOk()) {
- ALOGE("%s: Transaction error while disconnecting device %s", __FUNCTION__,
- ret.description().c_str());
+ ALOGE("%s: Transaction error while disconnecting device %d", __FUNCTION__,
+ ret.getExceptionCode());
}
}
mRemote = nullptr;
@@ -505,8 +513,7 @@
}
}
-camera_status_t
-CameraDevice::stopRepeatingLocked() {
+camera_status_t CameraDevice::stopRepeatingLocked() {
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
ALOGE("Camera %s stop repeating failed! ret %d", getId(), ret);
@@ -517,20 +524,14 @@
mRepeatingSequenceId = REQUEST_ID_NONE;
int64_t lastFrameNumber;
- Status status = Status::UNKNOWN_ERROR;
- auto remoteRet = mRemote->cancelRepeatingRequest(
- [&status, &lastFrameNumber](Status s, auto frameNumber) {
- status = s;
- lastFrameNumber = frameNumber;
- });
- CHECK_TRANSACTION_AND_RET(remoteRet, status, "cancelRepeatingRequest()");
+ ScopedAStatus remoteRet = mRemote->cancelRepeatingRequest(&lastFrameNumber);
+ CHECK_TRANSACTION_AND_RET(remoteRet, "cancelRepeatingRequest()");
checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
}
return ACAMERA_OK;
}
-camera_status_t
-CameraDevice::flushLocked(ACameraCaptureSession* session) {
+camera_status_t CameraDevice::flushLocked(ACameraCaptureSession* session) {
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
ALOGE("Camera %s abort captures failed! ret %d", getId(), ret);
@@ -571,20 +572,15 @@
}
int64_t lastFrameNumber;
- Status status = Status::UNKNOWN_ERROR;
- auto remoteRet = mRemote->flush([&status, &lastFrameNumber](auto s, auto frameNumber) {
- status = s;
- lastFrameNumber = frameNumber;
- });
- CHECK_TRANSACTION_AND_RET(remoteRet, status, "flush()")
+ ScopedAStatus remoteRet = mRemote->flush(&lastFrameNumber);
+ CHECK_TRANSACTION_AND_RET(remoteRet, "flush()")
if (mRepeatingSequenceId != REQUEST_ID_NONE) {
checkRepeatingSequenceCompleteLocked(mRepeatingSequenceId, lastFrameNumber);
}
return ACAMERA_OK;
}
-camera_status_t
-CameraDevice::waitUntilIdleLocked() {
+camera_status_t CameraDevice::waitUntilIdleLocked() {
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
ALOGE("Wait until camera %s idle failed! ret %d", getId(), ret);
@@ -597,13 +593,13 @@
}
auto remoteRet = mRemote->waitUntilIdle();
- CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "waitUntilIdle()")
+ CHECK_TRANSACTION_AND_RET(remoteRet, "waitUntilIdle()")
return ACAMERA_OK;
}
-camera_status_t
-CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outputs,
- const ACaptureRequest* sessionParameters, nsecs_t startTimeNs) {
+camera_status_t CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outputs,
+ const ACaptureRequest* sessionParameters,
+ nsecs_t startTimeNs) {
ACaptureSessionOutputContainer emptyOutput;
if (outputs == nullptr) {
outputs = &emptyOutput;
@@ -614,31 +610,37 @@
return ret;
}
- std::set<std::pair<native_handle_ptr_wrapper, OutputConfigurationWrapper>> outputSet;
- for (auto outConfig : outputs->mOutputs) {
- const native_handle_t* anw = outConfig.mWindow;
- OutputConfigurationWrapper outConfigInsertW;
- OutputConfiguration &outConfigInsert = outConfigInsertW.mOutputConfiguration;
- outConfigInsert.rotation = utils::convertToHidl(outConfig.mRotation);
+ std::map<native_handle_ptr_wrapper, OutputConfiguration> handleToConfig;
+ for (const auto& outConfig : outputs->mOutputs) {
+ native_handle_ptr_wrapper anw = outConfig.mWindow;
+ OutputConfiguration outConfigInsert;
+ outConfigInsert.rotation = utils::convertToAidl(outConfig.mRotation);
outConfigInsert.windowGroupId = -1;
outConfigInsert.windowHandles.resize(outConfig.mSharedWindows.size() + 1);
- outConfigInsert.windowHandles[0] = anw;
+ outConfigInsert.windowHandles[0] = std::move(dupToAidl(anw));
outConfigInsert.physicalCameraId = outConfig.mPhysicalCameraId;
- native_handle_ptr_wrapper wrap(anw);
-
- outputSet.emplace(std::make_pair(std::move(anw), std::move(outConfigInsertW)));
+ handleToConfig.insert({anw, std::move(outConfigInsert)});
}
- std::set<std::pair<native_handle_ptr_wrapper, OutputConfigurationWrapper>> addSet = outputSet;
+
+ std::set<native_handle_ptr_wrapper> addSet;
+ for (auto& kvPair : handleToConfig) {
+ addSet.insert(kvPair.first);
+ }
+
std::vector<int32_t> deleteList;
// Determine which streams need to be created, which to be deleted
for (auto& kvPair : mConfiguredOutputs) {
int32_t streamId = kvPair.first;
auto& outputPair = kvPair.second;
- if (outputSet.count(outputPair)) {
- deleteList.push_back(streamId); // Need to delete a no longer needed stream
+ auto& anw = outputPair.first;
+ auto& configuredOutput = outputPair.second;
+
+ auto itr = handleToConfig.find(anw);
+ if (itr != handleToConfig.end() && (itr->second) == configuredOutput) {
+ deleteList.push_back(streamId);
} else {
- addSet.erase(outputPair); // No need to add already existing stream
+ addSet.erase(anw);
}
}
@@ -673,106 +675,96 @@
mIdle = true;
auto remoteRet = mRemote->beginConfigure();
- CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "beginConfigure()")
+ CHECK_TRANSACTION_AND_RET(remoteRet, "beginConfigure()")
// delete to-be-deleted streams
for (auto streamId : deleteList) {
remoteRet = mRemote->deleteStream(streamId);
- CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "deleteStream()")
+ CHECK_TRANSACTION_AND_RET(remoteRet, "deleteStream()")
mConfiguredOutputs.erase(streamId);
}
// add new streams
- for (const auto &outputPair : addSet) {
- int streamId;
- Status status = Status::UNKNOWN_ERROR;
- auto ret = mRemote->createStream(outputPair.second,
- [&status, &streamId](Status s, auto stream_id) {
- status = s;
- streamId = stream_id;
- });
- CHECK_TRANSACTION_AND_RET(ret, status, "createStream()")
- mConfiguredOutputs.insert(std::make_pair(streamId, outputPair));
+ for (const auto &anw : addSet) {
+ int32_t streamId;
+ auto itr = handleToConfig.find(anw);
+ remoteRet = mRemote->createStream(itr->second, &streamId);
+ CHECK_TRANSACTION_AND_RET(remoteRet, "createStream()")
+ mConfiguredOutputs.insert(std::make_pair(streamId,
+ std::make_pair(anw,
+ std::move(itr->second))));
+ handleToConfig.erase(itr);
}
- CameraMetadata params;
- HCameraMetadata hidlParams;
+ AidlCameraMetadata aidlParams;
if ((sessionParameters != nullptr) && (sessionParameters->settings != nullptr)) {
- params.append(sessionParameters->settings->getInternalData());
- const camera_metadata_t *params_metadata = params.getAndLock();
- utils::convertToHidl(params_metadata, &hidlParams);
- params.unlock(params_metadata);
+ const CameraMetadata ¶ms = sessionParameters->settings->getInternalData();
+ const camera_metadata_t* paramsMetadata = params.getAndLock();
+ utils::convertToAidl(paramsMetadata, &aidlParams);
+ params.unlock(paramsMetadata);
}
- remoteRet = mRemote->endConfigure_2_1(StreamConfigurationMode::NORMAL_MODE,
- hidlParams, startTimeNs);
- CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "endConfigure()")
+ remoteRet = mRemote->endConfigure(StreamConfigurationMode::NORMAL_MODE,
+ aidlParams, startTimeNs);
+ CHECK_TRANSACTION_AND_RET(remoteRet, "endConfigure()")
return ACAMERA_OK;
}
-void
-CameraDevice::setRemoteDevice(sp<ICameraDeviceUser> remote) {
+void CameraDevice::setRemoteDevice(std::shared_ptr<ICameraDeviceUser> remote) {
Mutex::Autolock _l(mDeviceLock);
- mRemote = remote;
+ mRemote = std::move(remote);
}
-bool
-CameraDevice::setDeviceMetadataQueues() {
+bool CameraDevice::setDeviceMetadataQueues() {
if (mRemote == nullptr) {
ALOGE("mRemote must not be null while trying to fetch metadata queues");
return false;
}
std::shared_ptr<RequestMetadataQueue> &reqQueue = mCaptureRequestMetadataQueue;
- auto ret =
- mRemote->getCaptureRequestMetadataQueue(
- [&reqQueue](const auto &mqDescriptor) {
- reqQueue = std::make_shared<RequestMetadataQueue>(mqDescriptor);
- if (!reqQueue->isValid() || reqQueue->availableToWrite() <=0) {
- ALOGE("Empty fmq from cameraserver");
- reqQueue = nullptr;
- }
- });
+ MQDescriptor<int8_t, SynchronizedReadWrite> reqMqDescriptor;
+ ScopedAStatus ret = mRemote->getCaptureRequestMetadataQueue(&reqMqDescriptor);
if (!ret.isOk()) {
ALOGE("Transaction error trying to get capture request metadata queue");
return false;
}
+ reqQueue = std::make_shared<RequestMetadataQueue>(reqMqDescriptor);
+ if (!reqQueue->isValid() || reqQueue->availableToWrite() <= 0) {
+ ALOGE("Empty fmq from cameraserver");
+ reqQueue = nullptr;
+ }
+
+ MQDescriptor<int8_t, SynchronizedReadWrite> resMqDescriptor;
std::shared_ptr<ResultMetadataQueue> &resQueue = mCaptureResultMetadataQueue;
- ret =
- mRemote->getCaptureResultMetadataQueue(
- [&resQueue](const auto &mqDescriptor) {
- resQueue = std::make_shared<ResultMetadataQueue>(mqDescriptor);
- if (!resQueue->isValid() || resQueue->availableToWrite() <=0) {
- ALOGE("Empty fmq from cameraserver");
- }
- });
+ ret = mRemote->getCaptureResultMetadataQueue(&resMqDescriptor);
if (!ret.isOk()) {
ALOGE("Transaction error trying to get capture result metadata queue");
return false;
}
+ resQueue = std::make_shared<ResultMetadataQueue>(resMqDescriptor);
+ if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+ ALOGE("Empty fmq from cameraserver");
+ }
+
return true;
}
-camera_status_t
-CameraDevice::checkCameraClosedOrErrorLocked() const {
+camera_status_t CameraDevice::checkCameraClosedOrErrorLocked() const {
if (mRemote == nullptr) {
ALOGE("%s: camera device already closed", __FUNCTION__);
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
- if (mInError) {// triggered by onDeviceError
- ALOGE("%s: camera device has encountered a serious error", __FUNCTION__);
+ if (mInError) { // triggered by onDeviceError
+ ALOGE("%s: camera device has encountered a serious error: %d", __FUNCTION__, mError);
return mError;
}
return ACAMERA_OK;
}
-void
-CameraDevice::setCameraDeviceErrorLocked(camera_status_t error) {
+void CameraDevice::setCameraDeviceErrorLocked(camera_status_t error) {
mInError = true;
mError = error;
- return;
}
-void
-CameraDevice::FrameNumberTracker::updateTracker(int64_t frameNumber, bool isError) {
+void CameraDevice::FrameNumberTracker::updateTracker(int64_t frameNumber, bool isError) {
ALOGV("updateTracker frame %" PRId64 " isError %d", frameNumber, isError);
if (isError) {
mFutureErrorSet.insert(frameNumber);
@@ -791,8 +783,7 @@
update();
}
-void
-CameraDevice::FrameNumberTracker::update() {
+void CameraDevice::FrameNumberTracker::update() {
for (auto it = mFutureErrorSet.begin(); it != mFutureErrorSet.end();) {
int64_t errorFrameNumber = *it;
if (errorFrameNumber == mCompletedFrameNumber + 1) {
@@ -811,10 +802,8 @@
ALOGV("Update complete frame %" PRId64, mCompletedFrameNumber);
}
-void
-CameraDevice::onCaptureErrorLocked(
- ErrorCode errorCode,
- const CaptureResultExtras& resultExtras) {
+void CameraDevice::onCaptureErrorLocked(ErrorCode errorCode,
+ const CaptureResultExtras& resultExtras) {
int sequenceId = resultExtras.requestId;
int64_t frameNumber = resultExtras.frameNumber;
int32_t burstId = resultExtras.burstId;
@@ -826,7 +815,7 @@
return;
}
- CallbackHolder cbh = (*it).second;
+ CallbackHolder cbh = it->second;
sp<ACameraCaptureSession> session = cbh.mSession;
if ((size_t) burstId >= cbh.mRequests.size()) {
ALOGE("%s: Error: request index %d out of bound (size %zu)",
@@ -852,7 +841,7 @@
// them and try to match the surfaces in the corresponding
// CaptureRequest.
const auto& errorWindowHandles =
- outputPairIt->second.second.mOutputConfiguration.windowHandles;
+ outputPairIt->second.second.windowHandles;
for (const auto& errorWindowHandle : errorWindowHandles) {
for (const auto &requestStreamAndWindowId :
request->mCaptureRequest.streamAndWindowIds) {
@@ -869,11 +858,11 @@
}
const auto &requestWindowHandles =
- requestSurfacePairIt->second.second.mOutputConfiguration.windowHandles;
- if (utils::isWindowNativeHandleEqual(
- requestWindowHandles[requestWindowId], errorWindowHandle)) {
- const native_handle_t* anw =
- requestWindowHandles[requestWindowId].getNativeHandle();
+ requestSurfacePairIt->second.second.windowHandles;
+
+ if (requestWindowHandles[requestWindowId] == errorWindowHandle) {
+ const native_handle_t* anw = makeFromAidl(
+ requestWindowHandles[requestWindowId]);
ALOGV("Camera %s Lost output buffer for ANW %p frame %" PRId64,
getId(), anw, frameNumber);
@@ -898,14 +887,16 @@
failure->sequenceId = sequenceId;
failure->wasImageCaptured = (errorCode == ErrorCode::CAMERA_RESULT);
- sp<AMessage> msg = new AMessage(cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureFail :
- kWhatCaptureFail, mHandler);
+ sp<AMessage> msg = new AMessage(cbh.mIsLogicalCameraCallback ? kWhatLogicalCaptureFail
+ : kWhatCaptureFail,
+ mHandler);
msg->setPointer(kContextKey, cbh.mContext);
msg->setObject(kSessionSpKey, session);
if (cbh.mIsLogicalCameraCallback) {
- if (resultExtras.errorPhysicalCameraId.size() > 0) {
- msg->setString(kFailingPhysicalCameraId, resultExtras.errorPhysicalCameraId.c_str(),
- resultExtras.errorPhysicalCameraId.size());
+ if (!resultExtras.errorPhysicalCameraId.empty()) {
+ msg->setString(kFailingPhysicalCameraId,
+ resultExtras.errorPhysicalCameraId.c_str(),
+ resultExtras.errorPhysicalCameraId.size());
}
msg->setPointer(kCallbackFpKey, (void*) cbh.mOnLogicalCameraCaptureFailed);
} else {
@@ -919,7 +910,6 @@
mFrameNumberTracker.updateTracker(frameNumber, /*isError*/true);
checkAndFireSequenceCompleteLocked();
}
- return;
}
CameraDevice::CallbackHandler::CallbackHandler(const char *id) : mId(id) { }
@@ -1020,7 +1010,7 @@
return;
}
sp<ACameraCaptureSession> session(static_cast<ACameraCaptureSession*>(obj.get()));
- mCachedSessions.push(session);
+ mCachedSessions.push_back(session);
sp<CaptureRequest> requestSp = nullptr;
const char *id_cstr = mId.c_str();
switch (msg->what()) {
@@ -1167,7 +1157,8 @@
clone.update(ANDROID_SYNC_FRAME_NUMBER,
&physicalResult->mFrameNumber, /*data_count*/1);
sp<ACameraMetadata> metadata =
- new ACameraMetadata(clone.release(), ACameraMetadata::ACM_RESULT);
+ new ACameraMetadata(clone.release(),
+ ACameraMetadata::ACM_RESULT);
physicalMetadataCopy.push_back(metadata);
}
std::vector<const char*> physicalCameraIdPtrs;
@@ -1302,7 +1293,7 @@
return;
}
- const native_handle_t* anw;
+ native_handle_t* anw;
found = msg->findPointer(kAnwKey, (void**) &anw);
if (!found) {
ALOGE("%s: Cannot find native_handle_t!", __FUNCTION__);
@@ -1319,6 +1310,7 @@
ACaptureRequest* request = allocateACaptureRequest(requestSp, id_cstr);
(*onBufferLost)(context, session.get(), request, anw, frameNumber);
freeACaptureRequest(request);
+ native_handle_delete(anw); // clean up anw as it was copied from AIDL
break;
}
}
@@ -1329,10 +1321,10 @@
CameraDevice::CallbackHolder::CallbackHolder(
sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest> >& requests,
+ std::vector<sp<CaptureRequest>> requests,
bool isRepeating,
ACameraCaptureSession_captureCallbacks* cbs) :
- mSession(session), mRequests(requests),
+ mSession(std::move(session)), mRequests(std::move(requests)),
mIsRepeating(isRepeating),
mIs2Callback(false),
mIsLogicalCameraCallback(false) {
@@ -1346,10 +1338,10 @@
CameraDevice::CallbackHolder::CallbackHolder(
sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest> >& requests,
+ std::vector<sp<CaptureRequest>> requests,
bool isRepeating,
ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs) :
- mSession(session), mRequests(requests),
+ mSession(std::move(session)), mRequests(std::move(requests)),
mIsRepeating(isRepeating),
mIs2Callback(false),
mIsLogicalCameraCallback(true) {
@@ -1363,10 +1355,10 @@
CameraDevice::CallbackHolder::CallbackHolder(
sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest> >& requests,
+ std::vector<sp<CaptureRequest>> requests,
bool isRepeating,
ACameraCaptureSession_captureCallbacksV2* cbs) :
- mSession(session), mRequests(requests),
+ mSession(std::move(session)), mRequests(std::move(requests)),
mIsRepeating(isRepeating),
mIs2Callback(true),
mIsLogicalCameraCallback(false) {
@@ -1380,10 +1372,10 @@
CameraDevice::CallbackHolder::CallbackHolder(
sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest> >& requests,
+ std::vector<sp<CaptureRequest>> requests,
bool isRepeating,
ACameraCaptureSession_logicalCamera_captureCallbacksV2* lcbs) :
- mSession(session), mRequests(requests),
+ mSession(std::move(session)), mRequests(std::move(requests)),
mIsRepeating(isRepeating),
mIs2Callback(true),
mIsLogicalCameraCallback(true) {
@@ -1501,23 +1493,21 @@
/**
* Camera service callback implementation
*/
-android::hardware::Return<void>
-CameraDevice::ServiceCallback::onDeviceError(
- ErrorCode errorCode,
- const CaptureResultExtras& resultExtras) {
+ScopedAStatus CameraDevice::ServiceCallback::onDeviceError(
+ ErrorCode errorCode, const CaptureResultExtras& resultExtras) {
ALOGD("Device error received, code %d, frame number %" PRId64 ", request ID %d, subseq ID %d"
" physical camera ID %s", errorCode, resultExtras.frameNumber, resultExtras.requestId,
resultExtras.burstId, resultExtras.errorPhysicalCameraId.c_str());
- auto ret = Void();
- sp<CameraDevice> dev = mDevice.promote();
+
+ std::shared_ptr<CameraDevice> dev = mDevice.lock();
if (dev == nullptr) {
- return ret; // device has been closed
+ return ScopedAStatus::ok(); // device has been closed
}
sp<ACameraCaptureSession> session = dev->mCurrentSession.promote();
Mutex::Autolock _l(dev->mDeviceLock);
if (dev->mRemote == nullptr) {
- return ret; // device has been closed
+ return ScopedAStatus::ok(); // device has been closed
}
switch (errorCode) {
case ErrorCode::CAMERA_DISCONNECTED:
@@ -1570,26 +1560,25 @@
dev->onCaptureErrorLocked(errorCode, resultExtras);
break;
}
- return ret;
+ return ScopedAStatus::ok();
}
-android::hardware::Return<void>
-CameraDevice::ServiceCallback::onDeviceIdle() {
+ScopedAStatus CameraDevice::ServiceCallback::onDeviceIdle() {
ALOGV("Camera is now idle");
- auto ret = Void();
- sp<CameraDevice> dev = mDevice.promote();
+
+ std::shared_ptr<CameraDevice> dev = mDevice.lock();
if (dev == nullptr) {
- return ret; // device has been closed
+ return ScopedAStatus::ok(); // device has been closed
}
Mutex::Autolock _l(dev->mDeviceLock);
if (dev->isClosed() || dev->mRemote == nullptr) {
- return ret;
+ return ScopedAStatus::ok();
}
if (dev->mIdle) {
// Already in idle state. Possibly other thread did waitUntilIdle
- return ret;
+ return ScopedAStatus::ok();
}
if (dev->mCurrentSession != nullptr) {
@@ -1597,13 +1586,14 @@
if (dev->mBusySession != dev->mCurrentSession) {
ALOGE("Current session != busy session");
dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_DEVICE);
- return ret;
+ return ScopedAStatus::ok();
}
sp<AMessage> msg = new AMessage(kWhatSessionStateCb, dev->mHandler);
msg->setPointer(kContextKey, dev->mBusySession->mUserSessionCallback.context);
msg->setObject(kSessionSpKey, dev->mBusySession);
- msg->setPointer(kCallbackFpKey, (void*) dev->mBusySession->mUserSessionCallback.onReady);
+ msg->setPointer(kCallbackFpKey,
+ (void*) dev->mBusySession->mUserSessionCallback.onReady);
// Make sure we clear the sp first so the session destructor can
// only happen on handler thread (where we don't hold device/session lock)
dev->mBusySession.clear();
@@ -1611,22 +1601,20 @@
}
dev->mIdle = true;
dev->mFlushing = false;
- return ret;
+ return ScopedAStatus::ok();
}
-android::hardware::Return<void>
-CameraDevice::ServiceCallback::onCaptureStarted(
- const CaptureResultExtras& resultExtras,
- uint64_t timestamp) {
- auto ret = Void();
- sp<CameraDevice> dev = mDevice.promote();
+
+ndk::ScopedAStatus CameraDevice::ServiceCallback::onCaptureStarted(
+ const CaptureResultExtras& resultExtras, int64_t timestamp) {
+ std::shared_ptr<CameraDevice> dev = mDevice.lock();
if (dev == nullptr) {
- return ret; // device has been closed
+ return ScopedAStatus::ok(); // device has been closed
}
Mutex::Autolock _l(dev->mDeviceLock);
if (dev->isClosed() || dev->mRemote == nullptr) {
- return ret;
+ return ScopedAStatus::ok();
}
int32_t sequenceId = resultExtras.requestId;
@@ -1635,7 +1623,7 @@
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
- CallbackHolder cbh = (*it).second;
+ CallbackHolder &cbh = it->second;
ACameraCaptureSession_captureCallback_start onStart = cbh.mOnCaptureStarted;
ACameraCaptureSession_captureCallback_startV2 onStart2 = cbh.mOnCaptureStarted2;
bool v2Callback = cbh.mIs2Callback;
@@ -1646,6 +1634,7 @@
dev->setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
}
sp<CaptureRequest> request = cbh.mRequests[burstId];
+ ALOGE("%s: request = %p", __FUNCTION__, request.get());
sp<AMessage> msg = nullptr;
if (v2Callback) {
msg = new AMessage(kWhatCaptureStart2, dev->mHandler);
@@ -1661,24 +1650,22 @@
msg->setInt64(kFrameNumberKey, frameNumber);
dev->postSessionMsgAndCleanup(msg);
}
- return ret;
+ return ScopedAStatus::ok();
}
-android::hardware::Return<void>
-CameraDevice::ServiceCallback::onResultReceived(
- const FmqSizeOrMetadata& resultMetadata,
+ScopedAStatus CameraDevice::ServiceCallback::onResultReceived(
+ const CaptureMetadataInfo& resultMetadata,
const CaptureResultExtras& resultExtras,
- const hidl_vec<PhysicalCaptureResultInfo>& physicalResultInfos) {
- auto ret = Void();
+ const std::vector<PhysicalCaptureResultInfo>& physicalResultInfos) {
- sp<CameraDevice> dev = mDevice.promote();
+ std::shared_ptr<CameraDevice> dev = mDevice.lock();
if (dev == nullptr) {
- return ret; // device has been closed
+ return ScopedAStatus::ok(); // device has been closed
}
int32_t sequenceId = resultExtras.requestId;
int64_t frameNumber = resultExtras.frameNumber;
int32_t burstId = resultExtras.burstId;
- bool isPartialResult = (resultExtras.partialResultCount < dev->mPartialResultCount);
+ bool isPartialResult = (resultExtras.partialResultCount < dev->mPartialResultCount);
if (!isPartialResult) {
ALOGV("SeqId %d frame %" PRId64 " result arrive.", sequenceId, frameNumber);
@@ -1686,7 +1673,7 @@
Mutex::Autolock _l(dev->mDeviceLock);
if (dev->mRemote == nullptr) {
- return ret; // device has been disconnected
+ return ScopedAStatus::ok(); // device has been disconnected
}
if (dev->isClosed()) {
@@ -1694,7 +1681,7 @@
dev->mFrameNumberTracker.updateTracker(frameNumber, /*isError*/false);
}
// early return to avoid callback sent to closed devices
- return ret;
+ return ScopedAStatus::ok();
}
CameraMetadata metadataCopy;
@@ -1702,11 +1689,12 @@
dev->mCaptureResultMetadataQueue.get(), &metadataCopy);
if (status != ACAMERA_OK) {
ALOGE("%s: result metadata couldn't be converted", __FUNCTION__);
- return ret;
+ return ScopedAStatus::ok();
}
- metadataCopy.update(ANDROID_LENS_INFO_SHADING_MAP_SIZE, dev->mShadingMapSize, /*data_count*/2);
- metadataCopy.update(ANDROID_SYNC_FRAME_NUMBER, &frameNumber, /*data_count*/1);
+ metadataCopy.update(ANDROID_LENS_INFO_SHADING_MAP_SIZE, dev->mShadingMapSize,
+ /* data_count= */ 2);
+ metadataCopy.update(ANDROID_SYNC_FRAME_NUMBER, &frameNumber, /* data_count= */1);
auto it = dev->mSequenceCallbackMap.find(sequenceId);
if (it != dev->mSequenceCallbackMap.end()) {
@@ -1730,7 +1718,7 @@
&localPhysicalResult[i].physicalMetadata);
if (status != ACAMERA_OK) {
ALOGE("%s: physical camera result metadata couldn't be converted", __FUNCTION__);
- return ret;
+ return ScopedAStatus::ok();
}
}
sp<ACameraPhysicalCaptureResultInfo> physicalResult(
@@ -1762,17 +1750,14 @@
dev->checkAndFireSequenceCompleteLocked();
}
- return ret;
+ return ScopedAStatus::ok();
}
-android::hardware::Return<void>
-CameraDevice::ServiceCallback::onRepeatingRequestError(
- uint64_t lastFrameNumber, int32_t stoppedSequenceId) {
- auto ret = Void();
-
- sp<CameraDevice> dev = mDevice.promote();
+ScopedAStatus CameraDevice::ServiceCallback::onRepeatingRequestError(int64_t lastFrameNumber,
+ int32_t stoppedSequenceId) {
+ std::shared_ptr<CameraDevice> dev = mDevice.lock();
if (dev == nullptr) {
- return ret; // device has been closed
+ return ScopedAStatus::ok(); // device has been closed
}
Mutex::Autolock _l(dev->mDeviceLock);
@@ -1784,33 +1769,41 @@
dev->checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
- return ret;
+ return ScopedAStatus::ok();
}
camera_status_t CameraDevice::ServiceCallback::readOneResultMetadata(
- const FmqSizeOrMetadata& fmqSizeOrMetadata, ResultMetadataQueue* metadataQueue,
+ const CaptureMetadataInfo& captureMetadataInfo, ResultMetadataQueue* metadataQueue,
CameraMetadata* metadata) {
if (metadataQueue == nullptr || metadata == nullptr) {
return ACAMERA_ERROR_INVALID_PARAMETER;
}
bool converted;
- HCameraMetadata hCameraMetadata;
- if (fmqSizeOrMetadata.getDiscriminator() ==
- FmqSizeOrMetadata::hidl_discriminator::fmqMetadataSize) {
- hCameraMetadata.resize(fmqSizeOrMetadata.fmqMetadataSize());
- bool read = metadataQueue->read(
- hCameraMetadata.data(), fmqSizeOrMetadata.fmqMetadataSize());
+ AidlCameraMetadata aidlCameraMetadata;
+ std::vector<uint8_t>& metadataVec = aidlCameraMetadata.metadata;
+ camera_metadata_t* clonedMetadata;
+ if (captureMetadataInfo.getTag() == CaptureMetadataInfo::fmqMetadataSize) {
+ int64_t size = captureMetadataInfo.get<CaptureMetadataInfo::fmqMetadataSize>();
+ metadataVec.resize(size);
+ bool read = metadataQueue->read(reinterpret_cast<int8_t*>(metadataVec.data()), size);
if (!read) {
ALOGE("%s capture request settings could't be read from fmq", __FUNCTION__);
return ACAMERA_ERROR_UNKNOWN;
}
// TODO: Do we actually need to clone here ?
- converted = utils::convertFromHidlCloned(hCameraMetadata, metadata);
+ converted = utils::cloneFromAidl(aidlCameraMetadata, &clonedMetadata);
} else {
- converted = utils::convertFromHidlCloned(fmqSizeOrMetadata.metadata(), metadata);
+ const AidlCameraMetadata &embeddedMetadata =
+ captureMetadataInfo.get<CaptureMetadataInfo::metadata>();
+ converted = utils::cloneFromAidl(embeddedMetadata, &clonedMetadata);
}
- return converted ? ACAMERA_OK : ACAMERA_ERROR_UNKNOWN;
+ if (converted) {
+ *metadata = CameraMetadata(clonedMetadata);
+ return ACAMERA_OK;
+ }
+
+ return ACAMERA_ERROR_UNKNOWN;
}
} // namespace acam
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.h b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
index c306206..cad23aa 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.h
@@ -16,54 +16,63 @@
#ifndef _ACAMERA_DEVICE_H
#define _ACAMERA_DEVICE_H
-#include <memory>
-#include <map>
-#include <set>
-#include <atomic>
-#include <utility>
-#include <vector>
-#include <utils/StrongPointer.h>
-#include <utils/Mutex.h>
-#include <utils/List.h>
-#include <utils/Vector.h>
-#include <android/frameworks/cameraservice/device/2.1/ICameraDeviceUser.h>
-#include <android/frameworks/cameraservice/device/2.0/ICameraDeviceCallback.h>
-#include <android/frameworks/cameraservice/device/2.0/types.h>
-#include <fmq/MessageQueue.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/AHandler.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include <camera/NdkCameraManager.h>
-#include <camera/NdkCameraCaptureSession.h>
-
#include "ACameraMetadata.h"
#include "utils.h"
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/device/BnCameraDeviceCallback.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureResultExtras.h>
+#include <aidl/android/frameworks/cameraservice/device/ErrorCode.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureMetadataInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/ICameraDeviceUser.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCameraSettings.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCaptureResultInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/StreamConfigurationMode.h>
+#include <aidl/android/frameworks/cameraservice/device/SubmitInfo.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraStatusAndId.h>
+#include <atomic>
+#include <camera/NdkCameraCaptureSession.h>
+#include <camera/NdkCameraManager.h>
+#include <fmq/AidlMessageQueue.h>
+#include <fmq/MessageQueue.h>
+#include <map>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <memory>
+#include <set>
+#include <utility>
+#include <utils/List.h>
+#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
+#include <vector>
+
namespace android {
namespace acam {
-using ICameraDeviceCallback = frameworks::cameraservice::device::V2_0::ICameraDeviceCallback;
-using ICameraDeviceUser_2_0 = frameworks::cameraservice::device::V2_0::ICameraDeviceUser;
-using ICameraDeviceUser = frameworks::cameraservice::device::V2_1::ICameraDeviceUser;
-using CaptureResultExtras = frameworks::cameraservice::device::V2_0::CaptureResultExtras;
-using PhysicalCaptureResultInfo = frameworks::cameraservice::device::V2_0::PhysicalCaptureResultInfo;
-using PhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings;
-using SubmitInfo = frameworks::cameraservice::device::V2_0::SubmitInfo;
-using CaptureResultExtras = frameworks::cameraservice::device::V2_0::CaptureResultExtras;
-using ErrorCode = frameworks::cameraservice::device::V2_0::ErrorCode;
-using FmqSizeOrMetadata = frameworks::cameraservice::device::V2_0::FmqSizeOrMetadata;
-using StreamConfigurationMode = frameworks::cameraservice::device::V2_0::StreamConfigurationMode;
-using Status = frameworks::cameraservice::common::V2_0::Status;
-using ResultMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
-using RequestMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
-using CameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
+using ::aidl::android::frameworks::cameraservice::common::Status;
+using ::aidl::android::frameworks::cameraservice::device::BnCameraDeviceCallback;
+using ::aidl::android::frameworks::cameraservice::device::CaptureResultExtras;
+using ::aidl::android::frameworks::cameraservice::device::ErrorCode;
+using ::aidl::android::frameworks::cameraservice::device::CaptureMetadataInfo;
+using ::aidl::android::frameworks::cameraservice::device::ICameraDeviceCallback;
+using ::aidl::android::frameworks::cameraservice::device::ICameraDeviceUser;
+using ::aidl::android::frameworks::cameraservice::device::OutputConfiguration;
+using ::aidl::android::frameworks::cameraservice::device::PhysicalCameraSettings;
+using ::aidl::android::frameworks::cameraservice::device::PhysicalCaptureResultInfo;
+using ::aidl::android::frameworks::cameraservice::device::StreamConfigurationMode;
+using ::aidl::android::frameworks::cameraservice::device::SubmitInfo;
+using ::aidl::android::frameworks::cameraservice::service::CameraStatusAndId;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::acam::utils::native_handle_ptr_wrapper;
-using hardware::hidl_vec;
-using hardware::hidl_string;
-using utils::native_handle_ptr_wrapper;
+
+using ResultMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+using RequestMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+
using utils::CaptureRequest;
-using utils::OutputConfigurationWrapper;
// Wrap ACameraCaptureFailure so it can be ref-counted
struct CameraCaptureFailure : public RefBase, public ACameraCaptureFailure { };
@@ -83,13 +92,16 @@
int64_t mFrameNumber;
};
-class CameraDevice final : public RefBase {
+class CameraDevice final : public std::enable_shared_from_this<CameraDevice> {
public:
CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
sp<ACameraMetadata> chars,
ACameraDevice* wrapper);
~CameraDevice();
+ // Called to initialize fields that require shared_ptr to `this`
+ void init();
+
inline const char* getId() const { return mCameraId.c_str(); }
camera_status_t createCaptureRequest(
@@ -107,30 +119,35 @@
const ACaptureSessionOutputContainer* sessionOutputContainer) const;
// Callbacks from camera service
- class ServiceCallback : public ICameraDeviceCallback {
+ class ServiceCallback : public BnCameraDeviceCallback {
public:
- explicit ServiceCallback(CameraDevice* device) : mDevice(device) {}
- android::hardware::Return<void> onDeviceError(ErrorCode errorCode,
- const CaptureResultExtras& resultExtras) override;
- android::hardware::Return<void> onDeviceIdle() override;
- android::hardware::Return<void> onCaptureStarted(const CaptureResultExtras& resultExtras,
- uint64_t timestamp) override;
- android::hardware::Return<void> onResultReceived(const FmqSizeOrMetadata& result,
- const CaptureResultExtras& resultExtras,
- const hidl_vec<PhysicalCaptureResultInfo>& physicalResultInfos) override;
- android::hardware::Return<void> onRepeatingRequestError(uint64_t lastFrameNumber,
- int32_t stoppedSequenceId) override;
+ explicit ServiceCallback(std::weak_ptr<CameraDevice> device) :
+ mDevice(std::move(device)) {}
+
+ ndk::ScopedAStatus onDeviceError(ErrorCode in_errorCode,
+ const CaptureResultExtras& in_resultExtras) override;
+ ndk::ScopedAStatus onDeviceIdle() override;
+
+ ndk::ScopedAStatus onCaptureStarted(const CaptureResultExtras& in_resultExtras,
+ int64_t in_timestamp) override;
+ ndk::ScopedAStatus onRepeatingRequestError(int64_t in_lastFrameNumber,
+ int32_t in_repeatingRequestId) override;
+ ndk::ScopedAStatus onResultReceived(const CaptureMetadataInfo& in_result,
+ const CaptureResultExtras& in_resultExtras,
+ const std::vector<PhysicalCaptureResultInfo>&
+ in_physicalCaptureResultInfos) override;
+
private:
- camera_status_t readOneResultMetadata(const FmqSizeOrMetadata& fmqSizeOrMetadata,
+ camera_status_t readOneResultMetadata(const CaptureMetadataInfo& captureMetadataInfo,
ResultMetadataQueue* metadataQueue, CameraMetadata* metadata);
- const wp<CameraDevice> mDevice;
+ const std::weak_ptr<CameraDevice> mDevice;
};
- inline sp<ICameraDeviceCallback> getServiceCallback() {
+ inline std::shared_ptr<BnCameraDeviceCallback> getServiceCallback() {
return mServiceCallback;
};
// Camera device is only functional after remote being set
- void setRemoteDevice(sp<ICameraDeviceUser> remote);
+ void setRemoteDevice(std::shared_ptr<ICameraDeviceUser> remote);
bool setDeviceMetadataQueues();
inline ACameraDevice* getWrapper() const { return mWrapper; };
@@ -208,15 +225,15 @@
void postSessionMsgAndCleanup(sp<AMessage>& msg);
mutable Mutex mDeviceLock;
- const hidl_string mCameraId; // Camera ID
+ const std::string mCameraId; // Camera ID
const ACameraDevice_StateCallbacks mAppCallbacks; // Callback to app
const sp<ACameraMetadata> mChars; // Camera characteristics
- const sp<ServiceCallback> mServiceCallback;
+ std::shared_ptr<ServiceCallback> mServiceCallback;
ACameraDevice* mWrapper;
// stream id -> pair of (ACameraWindowType* from application, OutputConfiguration used for
// camera service)
- std::map<int, std::pair<native_handle_ptr_wrapper, OutputConfigurationWrapper>> mConfiguredOutputs;
+ std::map<int, std::pair<native_handle_ptr_wrapper, OutputConfiguration>> mConfiguredOutputs;
// TODO: maybe a bool will suffice for synchronous implementation?
std::atomic_bool mClosing;
@@ -232,7 +249,7 @@
// This will avoid a busy session being deleted before it's back to idle state
sp<ACameraCaptureSession> mBusySession;
- sp<ICameraDeviceUser> mRemote;
+ std::shared_ptr<ICameraDeviceUser> mRemote;
// Looper thread to handle callback to app
sp<ALooper> mCbLooper;
@@ -281,7 +298,7 @@
// This handler will cache all capture session sp until kWhatCleanUpSessions
// is processed. This is used to guarantee the last session reference is always
// being removed in callback thread without holding camera device lock
- Vector<sp<ACameraCaptureSession>> mCachedSessions;
+ std::vector<sp<ACameraCaptureSession>> mCachedSessions;
};
sp<CallbackHandler> mHandler;
@@ -303,19 +320,19 @@
struct CallbackHolder {
CallbackHolder(sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest>>& requests,
+ std::vector<sp<CaptureRequest>> requests,
bool isRepeating,
ACameraCaptureSession_captureCallbacks* cbs);
CallbackHolder(sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest>>& requests,
+ std::vector<sp<CaptureRequest>> requests,
bool isRepeating,
ACameraCaptureSession_logicalCamera_captureCallbacks* lcbs);
CallbackHolder(sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest> >& requests,
+ std::vector<sp<CaptureRequest> > requests,
bool isRepeating,
ACameraCaptureSession_captureCallbacksV2* cbs);
CallbackHolder(sp<ACameraCaptureSession> session,
- const Vector<sp<CaptureRequest> >& requests,
+ std::vector<sp<CaptureRequest> > requests,
bool isRepeating,
ACameraCaptureSession_logicalCamera_captureCallbacksV2* lcbs);
void clearCallbacks() {
@@ -359,7 +376,7 @@
}
sp<ACameraCaptureSession> mSession;
- Vector<sp<CaptureRequest>> mRequests;
+ std::vector<sp<CaptureRequest>> mRequests;
const bool mIsRepeating;
const bool mIs2Callback;
const bool mIsLogicalCameraCallback;
@@ -401,7 +418,7 @@
// Misc variables
int32_t mShadingMapSize[2]; // const after constructor
int32_t mPartialResultCount; // const after constructor
- std::shared_ptr<ResultMetadataQueue> mCaptureRequestMetadataQueue = nullptr;
+ std::shared_ptr<RequestMetadataQueue> mCaptureRequestMetadataQueue = nullptr;
std::shared_ptr<ResultMetadataQueue> mCaptureResultMetadataQueue = nullptr;
};
@@ -415,7 +432,10 @@
struct ACameraDevice {
ACameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
sp<ACameraMetadata> chars) :
- mDevice(new android::acam::CameraDevice(id, cb, std::move(chars), this)) {}
+ mDevice(std::make_shared<android::acam::CameraDevice>(id, cb,
+ std::move(chars), this)) {
+ mDevice->init();
+ }
~ACameraDevice();
/*******************
@@ -446,19 +466,20 @@
/***********************
* Device interal APIs *
***********************/
- inline android::sp<android::acam::ICameraDeviceCallback> getServiceCallback() {
+ inline std::shared_ptr<android::acam::BnCameraDeviceCallback> getServiceCallback() {
return mDevice->getServiceCallback();
};
// Camera device is only functional after remote being set
- inline void setRemoteDevice(android::sp<android::acam::ICameraDeviceUser> remote) {
+ inline void setRemoteDevice(std::shared_ptr<
+ ::aidl::android::frameworks::cameraservice::device::ICameraDeviceUser> remote) {
mDevice->setRemoteDevice(remote);
}
inline bool setDeviceMetadataQueues() {
return mDevice->setDeviceMetadataQueues();
}
private:
- android::sp<android::acam::CameraDevice> mDevice;
+ std::shared_ptr<android::acam::CameraDevice> mDevice;
};
#endif // _ACAMERA_DEVICE_H
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
index 8bd5a52..1e724eb 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
+++ b/camera/ndk/ndk_vendor/impl/ACameraDeviceVendor.inc
@@ -14,17 +14,14 @@
* limitations under the License.
*/
-#include <vector>
-#include <inttypes.h>
-#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
-#include <android/frameworks/cameraservice/device/2.0/types.h>
-#include <CameraMetadata.h>
-
-#include "ndk_vendor/impl/ACameraDevice.h"
#include "ACameraCaptureSession.h"
#include "ACameraMetadata.h"
#include "ACaptureRequest.h"
#include "utils.h"
+#include <CameraMetadata.h>
+#include <inttypes.h>
+#include <ndk_vendor/impl/ACameraDevice.h>
+#include <vector>
using namespace android;
@@ -32,22 +29,22 @@
namespace acam {
template<class T>
-camera_status_t
-CameraDevice::captureLocked(
+camera_status_t CameraDevice::captureLocked(
sp<ACameraCaptureSession> session,
/*optional*/T* cbs,
- int numRequests, ACaptureRequest** requests,
+ int numRequests,
+ ACaptureRequest** requests,
/*optional*/int* captureSequenceId) {
return submitRequestsLocked(
session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/false);
}
template<class T>
-camera_status_t
-CameraDevice::setRepeatingRequestsLocked(
+camera_status_t CameraDevice::setRepeatingRequestsLocked(
sp<ACameraCaptureSession> session,
/*optional*/T* cbs,
- int numRequests, ACaptureRequest** requests,
+ int numRequests,
+ ACaptureRequest** requests,
/*optional*/int* captureSequenceId) {
return submitRequestsLocked(
session, cbs, numRequests, requests, captureSequenceId, /*isRepeating*/true);
@@ -56,11 +53,10 @@
template<class T>
camera_status_t CameraDevice::submitRequestsLocked(
sp<ACameraCaptureSession> session,
- /*optional*/T* cbs,
- int numRequests, ACaptureRequest** requests,
+ /*optional*/T* cbs, int numRequests,
+ ACaptureRequest** requests,
/*out*/int* captureSequenceId,
- bool isRepeating)
-{
+ bool isRepeating) {
camera_status_t ret = checkCameraClosedOrErrorLocked();
if (ret != ACAMERA_OK) {
ALOGE("Camera %s submit capture request failed! ret %d", getId(), ret);
@@ -68,9 +64,10 @@
}
// Form two vectors of capture request, one for internal tracking
- std::vector<frameworks::cameraservice::device::V2_0::CaptureRequest> requestList;
- Vector<sp<CaptureRequest>> requestsV;
- requestsV.setCapacity(numRequests);
+
+ std::vector<::aidl::android::frameworks::cameraservice::device::CaptureRequest> requestList;
+ std::vector<sp<CaptureRequest>> requestsV;
+ requestsV.reserve(numRequests);
for (int i = 0; i < numRequests; i++) {
sp<CaptureRequest> req;
ret = allocateCaptureRequestLocked(requests[i], req);
@@ -87,7 +84,7 @@
ALOGE("Capture request without output target cannot be submitted!");
return ACAMERA_ERROR_INVALID_PARAMETER;
}
- requestList.push_back(utils::convertToHidl(req.get()));
+ requestList.push_back(utils::convertToAidl(req.get()));
requestsV.push_back(req);
}
if (isRepeating) {
@@ -100,18 +97,20 @@
SubmitInfo info;
Status status;
- auto remoteRet = mRemote->submitRequestList(requestList, isRepeating,
- [&status, &info](auto s, auto &submitInfo) {
- status = s;
- info = submitInfo;
- });
- if (!remoteRet.isOk()) {
- ALOGE("%s: Transaction error for submitRequestList call: %s", __FUNCTION__,
- remoteRet.description().c_str());
+ ndk::ScopedAStatus remoteRet = mRemote->submitRequestList(requestList, isRepeating, &info);
+ if (!remoteRet.isOk()) {
+ if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError());
+ ALOGE("%s: submitRequestList call failed: %s",
+ __FUNCTION__, toString(errStatus).c_str());
+ return utils::convertFromAidl(errStatus);
+ } else {
+ ALOGE("%s: Transaction error for submitRequestList call: %d", __FUNCTION__,
+ remoteRet.getExceptionCode());
+ return ACAMERA_ERROR_UNKNOWN;
+ }
}
- if (status != Status::NO_ERROR) {
- return utils::convertFromHidl(status);
- }
+
int32_t sequenceId = info.requestId;
int64_t lastFrameNumber = info.lastFrameNumber;
if (sequenceId < 0) {
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index bb4ef56..3aa7817 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -17,28 +17,29 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ACameraManagerVendor"
-#include <memory>
-#include "ndk_vendor/impl/ACameraManager.h"
#include "ACameraMetadata.h"
#include "ndk_vendor/impl/ACameraDevice.h"
+#include "ndk_vendor/impl/ACameraManager.h"
#include "utils.h"
+
#include <CameraMetadata.h>
-#include <camera_metadata_hidden.h>
-
-#include <utils/Vector.h>
-#include <cutils/properties.h>
-#include <stdlib.h>
-
#include <VendorTagDescriptor.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <camera_metadata_hidden.h>
+#include <cutils/properties.h>
+#include <memory>
+#include <utils/Vector.h>
using namespace android::acam;
namespace android {
namespace acam {
-using frameworks::cameraservice::common::V2_0::ProviderIdAndVendorTagSections;
-using android::hardware::camera::common::V1_0::helper::VendorTagDescriptor;
-using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
+using ::aidl::android::frameworks::cameraservice::common::ProviderIdAndVendorTagSections;
+using ::android::hardware::camera::common::V1_0::helper::VendorTagDescriptor;
+using ::android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
+using ::ndk::ScopedAStatus;
// Static member definitions
const char* CameraManagerGlobal::kCameraIdKey = "CameraId";
@@ -47,52 +48,55 @@
const char* CameraManagerGlobal::kContextKey = "CallbackContext";
const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms
Mutex CameraManagerGlobal::sLock;
-CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
+std::weak_ptr<CameraManagerGlobal> CameraManagerGlobal::sInstance =
+ std::weak_ptr<CameraManagerGlobal>();
/**
- * The vendor tag descriptor class that takes HIDL vendor tag information as
+ * The vendor tag descriptor class that takes AIDL vendor tag information as
* input. Not part of vendor available VendorTagDescriptor class because that class is used by
* default HAL implementation code as well.
+ *
+ * This is a class instead of a free-standing function because VendorTagDescriptor has some
+ * protected fields that need to be initialized during conversion.
*/
-class HidlVendorTagDescriptor : public VendorTagDescriptor {
+class AidlVendorTagDescriptor : public VendorTagDescriptor {
public:
/**
- * Create a VendorTagDescriptor object from the HIDL VendorTagSection
+ * Create a VendorTagDescriptor object from the AIDL VendorTagSection
* vector.
*
* Returns OK on success, or a negative error code.
*/
- static status_t createDescriptorFromHidl(const hidl_vec<VendorTagSection>& vts,
+ static status_t createDescriptorFromAidl(const std::vector<VendorTagSection>& vts,
/*out*/ sp<VendorTagDescriptor> *descriptor);
};
-status_t HidlVendorTagDescriptor::createDescriptorFromHidl(const hidl_vec<VendorTagSection> &vts,
- sp<VendorTagDescriptor> *descriptor) {
- int tagCount = 0;
+status_t AidlVendorTagDescriptor::createDescriptorFromAidl(const std::vector<VendorTagSection>& vts,
+ sp<VendorTagDescriptor>* descriptor){
+ size_t tagCount = 0;
for (size_t s = 0; s < vts.size(); s++) {
tagCount += vts[s].tags.size();
}
if (tagCount < 0 || tagCount > INT32_MAX) {
- ALOGE("%s: tag count %d from vendor tag sections is invalid.", __FUNCTION__, tagCount);
+ ALOGE("%s: tag count %zu from vendor tag sections is invalid.", __FUNCTION__, tagCount);
return BAD_VALUE;
}
- Vector<uint32_t> tagArray;
- LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
- "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
+ std::vector<int64_t> tagArray;
+ tagArray.resize(tagCount);
- sp<HidlVendorTagDescriptor> desc = new HidlVendorTagDescriptor();
+ sp<AidlVendorTagDescriptor> desc = new AidlVendorTagDescriptor();
desc->mTagCount = tagCount;
- KeyedVector<uint32_t, String8> tagToSectionMap;
+ std::map<int64_t, std::string> tagToSectionMap;
int idx = 0;
for (size_t s = 0; s < vts.size(); s++) {
const VendorTagSection& section = vts[s];
const char *sectionName = section.sectionName.c_str();
- if (sectionName == NULL) {
+ if (sectionName == nullptr) {
ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
return BAD_VALUE;
}
@@ -106,15 +110,15 @@
return BAD_VALUE;
}
- tagArray.editItemAt(idx++) = section.tags[j].tagId;
+ tagArray[idx++] = section.tags[j].tagId;
const char *tagName = section.tags[j].tagName.c_str();
- if (tagName == NULL) {
+ if (tagName == nullptr) {
ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag);
return BAD_VALUE;
}
desc->mTagToNameMap.add(tag, String8(tagName));
- tagToSectionMap.add(tag, sectionString);
+ tagToSectionMap.insert({tag, section.sectionName});
int tagType = (int) section.tags[j].tagType;
if (tagType < 0 || tagType >= NUM_TYPES) {
@@ -127,8 +131,12 @@
for (size_t i = 0; i < tagArray.size(); ++i) {
uint32_t tag = tagArray[i];
- String8 sectionString = tagToSectionMap.valueFor(tag);
-
+ auto itr = tagToSectionMap.find(tag);
+ if (itr == tagToSectionMap.end()) {
+ ALOGE("%s: Couldn't find previously added tag in map.", __FUNCTION__);
+ return UNKNOWN_ERROR;
+ }
+ String8 sectionString = String8(itr->second.c_str());
// Set up tag to section index map
ssize_t index = desc->mSections.indexOf(sectionString);
LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
@@ -147,38 +155,37 @@
return OK;
}
-CameraManagerGlobal&
-CameraManagerGlobal::getInstance() {
+std::shared_ptr<CameraManagerGlobal> CameraManagerGlobal::getInstance() {
Mutex::Autolock _l(sLock);
- CameraManagerGlobal* instance = sInstance;
+ std::shared_ptr<CameraManagerGlobal> instance = sInstance.lock();
if (instance == nullptr) {
- instance = new CameraManagerGlobal();
+ instance = std::make_shared<CameraManagerGlobal>();
sInstance = instance;
}
- return *instance;
+ return instance;
}
CameraManagerGlobal::~CameraManagerGlobal() {
- // clear sInstance so next getInstance call knows to create a new one
Mutex::Autolock _sl(sLock);
- sInstance = nullptr;
Mutex::Autolock _l(mLock);
if (mCameraService != nullptr) {
- mCameraService->unlinkToDeath(mDeathNotifier);
+ AIBinder_unlinkToDeath(mCameraService->asBinder().get(),
+ mDeathRecipient.get(), this);
auto stat = mCameraService->removeListener(mCameraServiceListener);
if (!stat.isOk()) {
- ALOGE("Failed to remove listener to camera service %s", stat.description().c_str());
+ ALOGE("Failed to remove listener to camera service %d:%d", stat.getExceptionCode(),
+ stat.getServiceSpecificError());
}
}
- mDeathNotifier.clear();
+
if (mCbLooper != nullptr) {
mCbLooper->unregisterHandler(mHandler->id());
mCbLooper->stop();
}
mCbLooper.clear();
mHandler.clear();
- mCameraServiceListener.clear();
- mCameraService.clear();
+ mCameraServiceListener.reset();
+ mCameraService.reset();
}
static bool isCameraServiceDisabled() {
@@ -191,23 +198,28 @@
sp<VendorTagDescriptorCache> tagCache = new VendorTagDescriptorCache();
Status status = Status::NO_ERROR;
std::vector<ProviderIdAndVendorTagSections> providerIdsAndVts;
- auto remoteRet = mCameraService->getCameraVendorTagSections([&status, &providerIdsAndVts]
- (Status s,
- auto &IdsAndVts) {
- status = s;
- providerIdsAndVts = IdsAndVts; });
+ ScopedAStatus remoteRet = mCameraService->getCameraVendorTagSections(&providerIdsAndVts);
- if (!remoteRet.isOk() || status != Status::NO_ERROR) {
- ALOGE("Failed to retrieve VendorTagSections %s", remoteRet.description().c_str());
+ if (!remoteRet.isOk()) {
+ if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError());
+ ALOGE("%s: Failed to retrieve VendorTagSections %s",
+ __FUNCTION__, toString(status).c_str());
+ } else {
+ ALOGE("%s: Binder error when retrieving VendorTagSections: %d", __FUNCTION__,
+ remoteRet.getExceptionCode());
+ }
return false;
}
+
// Convert each providers VendorTagSections into a VendorTagDescriptor and
// add it to the cache
for (auto &providerIdAndVts : providerIdsAndVts) {
sp<VendorTagDescriptor> vendorTagDescriptor;
- if (HidlVendorTagDescriptor::createDescriptorFromHidl(providerIdAndVts.vendorTagSections,
- &vendorTagDescriptor) != OK) {
- ALOGE("Failed to convert from Hidl: VendorTagDescriptor");
+ status_t ret = AidlVendorTagDescriptor::createDescriptorFromAidl(
+ providerIdAndVts.vendorTagSections, &vendorTagDescriptor);
+ if (ret != OK) {
+ ALOGE("Failed to convert from Aidl: VendorTagDescriptor: %d", ret);
return false;
}
tagCache->addVendorDescriptor(providerIdAndVts.providerId, vendorTagDescriptor);
@@ -216,101 +228,125 @@
return true;
}
-sp<ICameraService> CameraManagerGlobal::getCameraService() {
+std::shared_ptr<ICameraService> CameraManagerGlobal::getCameraService() {
Mutex::Autolock _l(mLock);
- if (mCameraService.get() == nullptr) {
- if (isCameraServiceDisabled()) {
- return mCameraService;
- }
- sp<ICameraService> cameraServiceBinder;
- do {
- cameraServiceBinder = ICameraService::getService();
- if (cameraServiceBinder != nullptr) {
- break;
- }
- ALOGW("CameraService not published, waiting...");
- usleep(kCameraServicePollDelay);
- } while(true);
- if (mDeathNotifier == nullptr) {
- mDeathNotifier = new DeathNotifier(this);
- }
- cameraServiceBinder->linkToDeath(mDeathNotifier, 0);
- mCameraService = cameraServiceBinder;
+ if (mCameraService != nullptr) {
+ // Camera service already set up. Return existing value.
+ return mCameraService;
+ }
- // Setup looper thread to perfrom availiability callbacks
- if (mCbLooper == nullptr) {
- mCbLooper = new ALooper;
- mCbLooper->setName("C2N-mgr-looper");
- status_t err = mCbLooper->start(
- /*runOnCallingThread*/false,
- /*canCallJava*/ true,
- PRIORITY_DEFAULT);
- if (err != OK) {
- ALOGE("%s: Unable to start camera service listener looper: %s (%d)",
- __FUNCTION__, strerror(-err), err);
- mCbLooper.clear();
- return nullptr;
- }
- if (mHandler == nullptr) {
- mHandler = new CallbackHandler(this);
- }
- mCbLooper->registerHandler(mHandler);
- }
+ if (isCameraServiceDisabled()) {
+ // Camera service is disabled. return nullptr.
+ return mCameraService;
+ }
- // register ICameraServiceListener
- if (mCameraServiceListener == nullptr) {
- mCameraServiceListener = new CameraServiceListener(this);
- }
- hidl_vec<frameworks::cameraservice::service::V2_1::CameraStatusAndId> cameraStatuses{};
- Status status = Status::NO_ERROR;
- auto remoteRet = mCameraService->addListener_2_1(mCameraServiceListener,
- [&status, &cameraStatuses](Status s,
- auto &retStatuses) {
- status = s;
- cameraStatuses = retStatuses;
- });
- if (!remoteRet.isOk() || status != Status::NO_ERROR) {
- ALOGE("Failed to add listener to camera service %s", remoteRet.description().c_str());
- }
+ std::string serviceName = ICameraService::descriptor;
+ serviceName += "/default";
- // Setup vendor tags
- if (!setupVendorTags()) {
- ALOGE("Unable to set up vendor tags");
+ bool isDeclared = AServiceManager_isDeclared(serviceName.c_str());
+ if (!isDeclared) {
+ ALOGE("%s: No ICameraService instance declared: %s", __FUNCTION__, serviceName.c_str());
+ return nullptr;
+ }
+
+ // Before doing any more make sure there is a binder threadpool alive
+ // This is a no-op if the binder threadpool was already started by this process.
+ ABinderProcess_startThreadPool();
+
+ std::shared_ptr<ICameraService> cameraService =
+ ICameraService::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService(serviceName.c_str())));
+ if (cameraService == nullptr) {
+ ALOGE("%s: Could not get ICameraService instance.", __FUNCTION__);
+ return nullptr;
+ }
+
+ if (mDeathRecipient.get() == nullptr) {
+ mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(
+ AIBinder_DeathRecipient_new(CameraManagerGlobal::binderDeathCallback));
+ }
+ AIBinder_linkToDeath(cameraService->asBinder().get(),
+ mDeathRecipient.get(), /*cookie=*/ this);
+
+ mCameraService = cameraService;
+
+ // Setup looper thread to perform availability callbacks
+ if (mCbLooper == nullptr) {
+ mCbLooper = new ALooper;
+ mCbLooper->setName("C2N-mgr-looper");
+ status_t err = mCbLooper->start(
+ /*runOnCallingThread*/false,
+ /*canCallJava*/ true,
+ PRIORITY_DEFAULT);
+ if (err != OK) {
+ ALOGE("%s: Unable to start camera service listener looper: %s (%d)",
+ __FUNCTION__, strerror(-err), err);
+ mCbLooper.clear();
return nullptr;
}
+ if (mHandler == nullptr) {
+ mHandler = new CallbackHandler(weak_from_this());
+ }
+ mCbLooper->registerHandler(mHandler);
+ }
- for (auto& c : cameraStatuses) {
- onStatusChangedLocked(c.v2_0);
+ // register ICameraServiceListener
+ if (mCameraServiceListener == nullptr) {
+ mCameraServiceListener = ndk::SharedRefBase::make<CameraServiceListener>(weak_from_this());
+ }
- for (auto& unavailablePhysicalId : c.unavailPhysicalCameraIds) {
- PhysicalCameraStatusAndId statusAndId;
- statusAndId.deviceStatus = CameraDeviceStatus::STATUS_NOT_PRESENT;
- statusAndId.cameraId = c.v2_0.cameraId;
- statusAndId.physicalCameraId = unavailablePhysicalId;
- onStatusChangedLocked(statusAndId);
- }
+ std::vector<CameraStatusAndId> cameraStatuses;
+ Status status = Status::NO_ERROR;
+ ScopedAStatus remoteRet = mCameraService->addListener(mCameraServiceListener,
+ &cameraStatuses);
+
+ if (!remoteRet.isOk()) {
+ if (remoteRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ Status errStatus = static_cast<Status>(remoteRet.getServiceSpecificError());
+ ALOGE("%s: Failed to add listener to camera service: %s", __FUNCTION__,
+ toString(errStatus).c_str());
+ } else {
+ ALOGE("%s: Transaction failed when adding listener to camera service: %d",
+ __FUNCTION__, remoteRet.getExceptionCode());
+ }
+ }
+
+ // Setup vendor tags
+ if (!setupVendorTags()) {
+ ALOGE("Unable to set up vendor tags");
+ return nullptr;
+ }
+
+ for (auto& csi: cameraStatuses){
+ onStatusChangedLocked(csi.deviceStatus, csi.cameraId);
+
+ for (auto& unavailablePhysicalId : csi.unavailPhysicalCameraIds) {
+ onStatusChangedLocked(CameraDeviceStatus::STATUS_NOT_PRESENT,
+ csi.cameraId, unavailablePhysicalId);
}
}
return mCameraService;
}
-void CameraManagerGlobal::DeathNotifier::serviceDied(uint64_t cookie, const wp<IBase> &who) {
- (void) cookie;
- (void) who;
+void CameraManagerGlobal::binderDeathCallback(void* /*cookie*/) {
+ AutoMutex _l(sLock);
+
ALOGE("Camera service binderDied!");
- sp<CameraManagerGlobal> cm = mCameraManager.promote();
- if (cm != nullptr) {
- AutoMutex lock(cm->mLock);
- for (auto& pair : cm->mDeviceStatusMap) {
- CameraStatusAndId cameraStatusAndId;
- cameraStatusAndId.cameraId = pair.first;
- cameraStatusAndId.deviceStatus = pair.second.getStatus();
- cm->onStatusChangedLocked(cameraStatusAndId);
- }
- cm->mCameraService.clear();
- // TODO: consider adding re-connect call here?
+ std::shared_ptr<CameraManagerGlobal> instance = sInstance.lock();
+ if (instance == nullptr) {
+ return;
}
+
+ // Remove cameraService from the static instance
+ AutoMutex lock(instance->mLock);
+ for (auto& pair : instance->mDeviceStatusMap) {
+ const auto &cameraId = pair.first;
+ const auto &deviceStatus = pair.second.getStatus();
+ instance->onStatusChangedLocked(deviceStatus, cameraId);
+ }
+ instance->mCameraService.reset();
+ // TODO: consider adding re-connect call here?
}
void CameraManagerGlobal::registerAvailabilityCallback(
@@ -362,41 +398,45 @@
void CameraManagerGlobal::registerAvailCallback(const T *callback) {
Mutex::Autolock _l(mLock);
Callback cb(callback);
- auto pair = mCallbacks.insert(cb);
+ auto res = mCallbacks.insert(cb);
+ if (!res.second) {
+ ALOGE("%s: Failed to register callback. Couldn't insert in map.", __FUNCTION__);
+ return;
+ }
// Send initial callbacks if callback is newly registered
- if (pair.second) {
- for (auto& pair : mDeviceStatusMap) {
- const hidl_string& cameraId = pair.first;
- CameraDeviceStatus status = pair.second.getStatus();
+ for (auto& pair : mDeviceStatusMap) {
+ const std::string& cameraId = pair.first;
+ CameraDeviceStatus status = pair.second.getStatus();
+ {
// Camera available/unavailable callback
sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
ACameraManager_AvailabilityCallback cbFunc = isStatusAvailable(status) ?
- cb.mAvailable : cb.mUnavailable;
+ cb.mAvailable : cb.mUnavailable;
msg->setPointer(kCallbackFpKey, (void *) cbFunc);
msg->setPointer(kContextKey, cb.mContext);
msg->setString(kCameraIdKey, AString(cameraId.c_str()));
mPendingCallbackCnt++;
msg->post();
+ }
- // Physical camera unavailable callback
- std::set<hidl_string> unavailPhysicalIds = pair.second.getUnavailablePhysicalIds();
- for (const auto& physicalCameraId : unavailPhysicalIds) {
- sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
- ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
- cb.mPhysicalCamUnavailable;
- msg->setPointer(kCallbackFpKey, (void *) cbFunc);
- msg->setPointer(kContextKey, cb.mContext);
- msg->setString(kCameraIdKey, AString(cameraId.c_str()));
- msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
- mPendingCallbackCnt++;
- msg->post();
- }
+ // Physical camera unavailable callback
+ std::set<std::string> unavailPhysicalIds = pair.second.getUnavailablePhysicalIds();
+ for (const auto& physicalCameraId : unavailPhysicalIds) {
+ sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
+ ACameraManager_PhysicalCameraAvailabilityCallback cbFunc =
+ cb.mPhysicalCamUnavailable;
+ msg->setPointer(kCallbackFpKey, (void *) cbFunc);
+ msg->setPointer(kContextKey, cb.mContext);
+ msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+ msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
+ mPendingCallbackCnt++;
+ msg->post();
}
}
}
-void CameraManagerGlobal::getCameraIdList(std::vector<hidl_string>* cameraIds) {
+void CameraManagerGlobal::getCameraIdList(std::vector<std::string>* cameraIds) {
// Ensure that we have initialized/refreshed the list of available devices
auto cs = getCameraService();
Mutex::Autolock _l(mLock);
@@ -507,33 +547,31 @@
}
void CameraManagerGlobal::CallbackHandler::notifyParent() {
- sp<CameraManagerGlobal> parent = mParent.promote();
+ std::shared_ptr<CameraManagerGlobal> parent = mParent.lock();
if (parent != nullptr) {
parent->onCallbackCalled();
}
}
-hardware::Return<void> CameraManagerGlobal::CameraServiceListener::onStatusChanged(
- const CameraStatusAndId &statusAndId) {
- sp<CameraManagerGlobal> cm = mCameraManager.promote();
+ScopedAStatus CameraManagerGlobal::CameraServiceListener::onStatusChanged(
+ CameraDeviceStatus status, const std::string &cameraId) {
+ std::shared_ptr<CameraManagerGlobal> cm = mCameraManager.lock();
if (cm != nullptr) {
- cm->onStatusChanged(statusAndId);
+ cm->onStatusChanged(status, cameraId);
} else {
ALOGE("Cannot deliver status change. Global camera manager died");
}
- return Void();
+ return ScopedAStatus::ok();
}
void CameraManagerGlobal::onStatusChanged(
- const CameraStatusAndId &statusAndId) {
+ const CameraDeviceStatus &status, const std::string &cameraId) {
Mutex::Autolock _l(mLock);
- onStatusChangedLocked(statusAndId);
+ onStatusChangedLocked(status, cameraId);
}
void CameraManagerGlobal::onStatusChangedLocked(
- const CameraStatusAndId &statusAndId) {
- hidl_string cameraId = statusAndId.cameraId;
- CameraDeviceStatus status = statusAndId.deviceStatus;
+ const CameraDeviceStatus &status, const std::string &cameraId) {
if (!validStatus(status)) {
ALOGE("%s: Invalid status %d", __FUNCTION__, status);
return;
@@ -567,28 +605,28 @@
}
}
-hardware::Return<void> CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
- const PhysicalCameraStatusAndId &statusAndId) {
- sp<CameraManagerGlobal> cm = mCameraManager.promote();
+ScopedAStatus CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
+ CameraDeviceStatus in_status, const std::string& in_cameraId,
+ const std::string& in_physicalCameraId) {
+ std::shared_ptr<CameraManagerGlobal> cm = mCameraManager.lock();
if (cm != nullptr) {
- cm->onStatusChanged(statusAndId);
+ cm->onStatusChanged(in_status, in_cameraId, in_physicalCameraId);
} else {
ALOGE("Cannot deliver status change. Global camera manager died");
}
- return Void();
+ return ScopedAStatus::ok();
}
void CameraManagerGlobal::onStatusChanged(
- const PhysicalCameraStatusAndId &statusAndId) {
+ const CameraDeviceStatus &status, const std::string& cameraId,
+ const std::string& physicalCameraId) {
Mutex::Autolock _l(mLock);
- onStatusChangedLocked(statusAndId);
+ onStatusChangedLocked(status, cameraId, physicalCameraId);
}
void CameraManagerGlobal::onStatusChangedLocked(
- const PhysicalCameraStatusAndId &statusAndId) {
- hidl_string cameraId = statusAndId.cameraId;
- hidl_string physicalCameraId = statusAndId.physicalCameraId;
- CameraDeviceStatus status = statusAndId.deviceStatus;
+ const CameraDeviceStatus &status, const std::string& cameraId,
+ const std::string& physicalCameraId) {
if (!validStatus(status)) {
ALOGE("%s: Invalid status %d", __FUNCTION__, status);
return;
@@ -642,20 +680,20 @@
}
bool CameraManagerGlobal::CameraStatus::addUnavailablePhysicalId(
- const hidl_string& physicalCameraId) {
+ const std::string& physicalCameraId) {
std::lock_guard<std::mutex> lock(mLock);
auto result = unavailablePhysicalIds.insert(physicalCameraId);
return result.second;
}
bool CameraManagerGlobal::CameraStatus::removeUnavailablePhysicalId(
- const hidl_string& physicalCameraId) {
+ const std::string& physicalCameraId) {
std::lock_guard<std::mutex> lock(mLock);
auto count = unavailablePhysicalIds.erase(physicalCameraId);
return count > 0;
}
-std::set<hidl_string> CameraManagerGlobal::CameraStatus::getUnavailablePhysicalIds() {
+std::set<std::string> CameraManagerGlobal::CameraStatus::getUnavailablePhysicalIds() {
std::lock_guard<std::mutex> lock(mLock);
return unavailablePhysicalIds;
}
@@ -666,16 +704,15 @@
/**
* ACameraManger Implementation
*/
-camera_status_t
-ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
+camera_status_t ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
Mutex::Autolock _l(mLock);
- std::vector<hidl_string> idList;
- CameraManagerGlobal::getInstance().getCameraIdList(&idList);
+ std::vector<std::string> idList;
+ CameraManagerGlobal::getInstance()->getCameraIdList(&idList);
int numCameras = idList.size();
ACameraIdList *out = new ACameraIdList;
- if (!out) {
+ if (out == nullptr) {
ALOGE("Allocate memory for ACameraIdList failed!");
return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
}
@@ -717,33 +754,37 @@
}
}
-camera_status_t ACameraManager::getCameraCharacteristics(
- const char *cameraIdStr, sp<ACameraMetadata> *characteristics) {
+camera_status_t ACameraManager::getCameraCharacteristics(const char *cameraIdStr,
+ sp<ACameraMetadata> *characteristics) {
+ using AidlCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
Mutex::Autolock _l(mLock);
- sp<ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+ std::shared_ptr<ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
if (cs == nullptr) {
ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
- CameraMetadata rawMetadata;
- Status status = Status::NO_ERROR;
- auto serviceRet =
- cs->getCameraCharacteristics(cameraIdStr,
- [&status, &rawMetadata] (auto s ,
- const hidl_vec<uint8_t> &metadata) {
- status = s;
- if (status == Status::NO_ERROR) {
- utils::convertFromHidlCloned(metadata, &rawMetadata);
- }
- });
- if (!serviceRet.isOk() || status != Status::NO_ERROR) {
- ALOGE("Get camera characteristics from camera service failed");
+ AidlCameraMetadata rawMetadata;
+ ScopedAStatus serviceRet = cs->getCameraCharacteristics(cameraIdStr, &rawMetadata);
+
+ if (!serviceRet.isOk()) {
+ if (serviceRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ Status errStatus = static_cast<Status>(serviceRet.getServiceSpecificError());
+ ALOGE("%s: Get camera characteristics from camera service failed: %s",
+ __FUNCTION__, toString(errStatus).c_str());
+ } else {
+ ALOGE("%s: Transaction error when getting camera "
+ "characteristics from camera service: %d",
+ __FUNCTION__, serviceRet.getExceptionCode());
+ }
return ACAMERA_ERROR_UNKNOWN; // should not reach here
}
- *characteristics = new ACameraMetadata(
- rawMetadata.release(), ACameraMetadata::ACM_CHARACTERISTICS);
+ camera_metadata_t* metadataBuffer;
+ ::android::acam::utils::cloneFromAidl(rawMetadata, &metadataBuffer);
+
+ *characteristics = new ACameraMetadata(metadataBuffer,
+ ACameraMetadata::ACM_CHARACTERISTICS);
return ACAMERA_OK;
}
@@ -763,42 +804,41 @@
ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(rawChars));
- sp<ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
+ std::shared_ptr<ICameraService> cs = CameraManagerGlobal::getInstance()->getCameraService();
if (cs == nullptr) {
ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
delete device;
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
- sp<ICameraDeviceCallback> callbacks = device->getServiceCallback();
- sp<ICameraDeviceUser_2_0> deviceRemote_2_0;
+ std::shared_ptr<BnCameraDeviceCallback> deviceCallback = device->getServiceCallback();
+ std::shared_ptr<ICameraDeviceUser> deviceRemote;
// No way to get package name from native.
// Send a zero length package name and let camera service figure it out from UID
- Status status = Status::NO_ERROR;
- auto serviceRet = cs->connectDevice(
- callbacks, cameraId, [&status, &deviceRemote_2_0](auto s, auto &device) {
- status = s;
- deviceRemote_2_0 = device;
- });
-
- if (!serviceRet.isOk() || status != Status::NO_ERROR) {
- ALOGE("%s: connect camera device failed", __FUNCTION__);
- delete device;
- return utils::convertFromHidl(status);
+ ScopedAStatus serviceRet = cs->connectDevice(deviceCallback,
+ std::string(cameraId), &deviceRemote);
+ if (!serviceRet.isOk()) {
+ if (serviceRet.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ Status errStatus = static_cast<Status>(serviceRet.getServiceSpecificError());
+ ALOGE("%s: connect camera device failed: %s",
+ __FUNCTION__, toString(errStatus).c_str());
+ delete device;
+ return utils::convertFromAidl(errStatus);
+ } else {
+ ALOGE("%s: Transaction failed when connecting camera device: %d",
+ __FUNCTION__, serviceRet.getExceptionCode());
+ delete device;
+ return ACAMERA_ERROR_UNKNOWN;
+ }
}
- if (deviceRemote_2_0 == nullptr) {
+
+ if (deviceRemote == nullptr) {
ALOGE("%s: connect camera device failed! remote device is null", __FUNCTION__);
delete device;
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
- auto castResult = ICameraDeviceUser::castFrom(deviceRemote_2_0);
- if (!castResult.isOk()) {
- ALOGE("%s: failed to cast remote device to version 2.1", __FUNCTION__);
- delete device;
- return ACAMERA_ERROR_CAMERA_DISCONNECTED;
- }
- sp<ICameraDeviceUser> deviceRemote = castResult;
+
device->setRemoteDevice(deviceRemote);
device->setDeviceMetadataQueues();
*outDevice = device;
@@ -821,7 +861,7 @@
sp<VendorTagDescriptorCache> vtCache = VendorTagDescriptorCache::getGlobalVendorTagCache();
sp<VendorTagDescriptor> vTags = nullptr;
vtCache->getVendorTagDescriptor(vendorTagId, &vTags);
- status_t status= metadata.getTagFromName(name, vTags.get(), tag);
+ status_t status = CameraMetadata::getTagFromName(name, vTags.get(), tag);
return status == OK ? ACAMERA_OK : ACAMERA_ERROR_METADATA_NOT_FOUND;
}
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h
index 4663529..85acee7 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h
@@ -17,39 +17,35 @@
#ifndef _ACAMERA_MANAGER_H
#define _ACAMERA_MANAGER_H
-#include <camera/NdkCameraManager.h>
-
-#include <android-base/parseint.h>
-#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
-#include <android/frameworks/cameraservice/service/2.1/ICameraService.h>
-#include <android/frameworks/cameraservice/service/2.2/ICameraService.h>
-#include <android/frameworks/cameraservice/service/2.1/ICameraServiceListener.h>
-
#include <CameraMetadata.h>
-#include <utils/StrongPointer.h>
-#include <utils/Mutex.h>
-
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/AHandler.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include <set>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/common/VendorTag.h>
+#include <aidl/android/frameworks/cameraservice/common/VendorTagSection.h>
+#include <aidl/android/frameworks/cameraservice/service/BnCameraServiceListener.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraDeviceStatus.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraStatusAndId.h>
+#include <aidl/android/frameworks/cameraservice/service/ICameraService.h>
+#include <android-base/parseint.h>
+#include <camera/NdkCameraManager.h>
#include <map>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <set>
+#include <utility>
+#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
namespace android {
namespace acam {
-using ICameraService = frameworks::cameraservice::service::V2_2::ICameraService;
-using CameraDeviceStatus = frameworks::cameraservice::service::V2_0::CameraDeviceStatus;
-using ICameraServiceListener = frameworks::cameraservice::service::V2_1::ICameraServiceListener;
-using PhysicalCameraStatusAndId = frameworks::cameraservice::service::V2_1::PhysicalCameraStatusAndId;
-using CameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
-using Status = frameworks::cameraservice::common::V2_0::Status;
-using VendorTagSection = frameworks::cameraservice::common::V2_0::VendorTagSection;
-using VendorTag = frameworks::cameraservice::common::V2_0::VendorTag;
-using IBase = android::hidl::base::V1_0::IBase;
-using android::hardware::hidl_string;
-using hardware::Void;
+using ::aidl::android::frameworks::cameraservice::common::Status;
+using ::aidl::android::frameworks::cameraservice::common::VendorTag;
+using ::aidl::android::frameworks::cameraservice::common::VendorTagSection;
+using ::aidl::android::frameworks::cameraservice::service::BnCameraServiceListener;
+using ::aidl::android::frameworks::cameraservice::service::CameraDeviceStatus;
+using ::aidl::android::frameworks::cameraservice::service::CameraStatusAndId;
+using ::aidl::android::frameworks::cameraservice::service::ICameraService;
/**
* Per-process singleton instance of CameraManger. Shared by all ACameraManager
@@ -58,15 +54,18 @@
*
* TODO: maybe CameraManagerGlobal is better suited in libcameraclient?
*/
-class CameraManagerGlobal final : public RefBase {
+class CameraManagerGlobal final: public std::enable_shared_from_this<CameraManagerGlobal> {
public:
- static CameraManagerGlobal& getInstance();
- sp<ICameraService> getCameraService();
+ static std::shared_ptr<CameraManagerGlobal> getInstance();
+ static void binderDeathCallback(void* cookie);
- void registerAvailabilityCallback(
- const ACameraManager_AvailabilityCallbacks *callback);
- void unregisterAvailabilityCallback(
- const ACameraManager_AvailabilityCallbacks *callback);
+ CameraManagerGlobal() {};
+ ~CameraManagerGlobal();
+
+ std::shared_ptr<ICameraService> getCameraService();
+
+ void registerAvailabilityCallback(const ACameraManager_AvailabilityCallbacks *callback);
+ void unregisterAvailabilityCallback(const ACameraManager_AvailabilityCallbacks *callback);
void registerExtendedAvailabilityCallback(
const ACameraManager_ExtendedAvailabilityCallbacks* callback);
@@ -76,35 +75,28 @@
/**
* Return camera IDs that support camera2
*/
- void getCameraIdList(std::vector<hidl_string> *cameraIds);
+ void getCameraIdList(std::vector<std::string> *cameraIds);
private:
- sp<ICameraService> mCameraService;
+ std::shared_ptr<ICameraService> mCameraService;
const int kCameraServicePollDelay = 500000; // 0.5s
Mutex mLock;
- class DeathNotifier : public android::hardware::hidl_death_recipient {
- public:
- explicit DeathNotifier(CameraManagerGlobal* cm) : mCameraManager(cm) {}
- protected:
- // IBinder::DeathRecipient implementation
- virtual void serviceDied(uint64_t cookie, const wp<IBase> &who);
- private:
- const wp<CameraManagerGlobal> mCameraManager;
- };
- sp<DeathNotifier> mDeathNotifier;
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
- class CameraServiceListener final : public ICameraServiceListener {
+ class CameraServiceListener final : public BnCameraServiceListener {
public:
- explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
- android::hardware::Return<void> onStatusChanged(
- const CameraStatusAndId &statusAndId) override;
- android::hardware::Return<void> onPhysicalCameraStatusChanged(
- const PhysicalCameraStatusAndId &statusAndId) override;
+ explicit CameraServiceListener(std::weak_ptr<CameraManagerGlobal> cm) :
+ mCameraManager(std::move(cm)) {}
+ ndk::ScopedAStatus onPhysicalCameraStatusChanged(
+ CameraDeviceStatus in_status, const std::string& in_cameraId,
+ const std::string& in_physicalCameraId) override;
+ ndk::ScopedAStatus onStatusChanged(CameraDeviceStatus in_status,
+ const std::string& in_cameraId) override;
private:
- const wp<CameraManagerGlobal> mCameraManager;
+ const std::weak_ptr<CameraManagerGlobal> mCameraManager;
};
- sp<CameraServiceListener> mCameraServiceListener;
+ std::shared_ptr<CameraServiceListener> mCameraServiceListener;
// Wrapper of ACameraManager_AvailabilityCallbacks so we can store it in std::set
struct Callback {
@@ -180,20 +172,22 @@
static const nsecs_t kCallbackDrainTimeout;
class CallbackHandler : public AHandler {
public:
- CallbackHandler(wp<CameraManagerGlobal> parent) : mParent(parent) {}
+ CallbackHandler(std::weak_ptr<CameraManagerGlobal> parent) : mParent(std::move(parent)) {}
void onMessageReceived(const sp<AMessage> &msg) override;
private:
- wp<CameraManagerGlobal> mParent;
+ std::weak_ptr<CameraManagerGlobal> mParent;
void notifyParent();
void onMessageReceivedInternal(const sp<AMessage> &msg);
};
sp<CallbackHandler> mHandler;
sp<ALooper> mCbLooper; // Looper thread where callbacks actually happen on
- void onStatusChanged(const CameraStatusAndId &statusAndId);
- void onStatusChangedLocked(const CameraStatusAndId &statusAndId);
- void onStatusChanged(const PhysicalCameraStatusAndId &statusAndId);
- void onStatusChangedLocked(const PhysicalCameraStatusAndId &statusAndId);
+ void onStatusChanged(const CameraDeviceStatus &status, const std::string &cameraId);
+ void onStatusChangedLocked(const CameraDeviceStatus &status, const std::string &cameraId);
+ void onStatusChanged(const CameraDeviceStatus &status, const std::string &cameraId,
+ const std::string &physicalCameraId);
+ void onStatusChangedLocked(const CameraDeviceStatus &status, const std::string &cameraId,
+ const std::string &physicalCameraId);
bool setupVendorTags();
// Utils for status
@@ -203,7 +197,7 @@
// The sort logic must match the logic in
// libcameraservice/common/CameraProviderManager.cpp::getAPI1CompatibleCameraDeviceIds
struct CameraIdComparator {
- bool operator()(const hidl_string& a, const hidl_string& b) const {
+ bool operator()(const std::string& a, const std::string& b) const {
uint32_t aUint = 0, bUint = 0;
bool aIsUint = base::ParseUint(a.c_str(), &aUint);
bool bIsUint = base::ParseUint(b.c_str(), &bUint);
@@ -225,29 +219,29 @@
private:
CameraDeviceStatus status = CameraDeviceStatus::STATUS_NOT_PRESENT;
mutable std::mutex mLock;
- std::set<hidl_string> unavailablePhysicalIds;
+ std::set<std::string> unavailablePhysicalIds;
public:
CameraStatus(CameraDeviceStatus st): status(st) { };
CameraStatus() = default;
- bool addUnavailablePhysicalId(const hidl_string& physicalCameraId);
- bool removeUnavailablePhysicalId(const hidl_string& physicalCameraId);
+ bool addUnavailablePhysicalId(const std::string& physicalCameraId);
+ bool removeUnavailablePhysicalId(const std::string& physicalCameraId);
CameraDeviceStatus getStatus();
void updateStatus(CameraDeviceStatus newStatus);
- std::set<hidl_string> getUnavailablePhysicalIds();
+ std::set<std::string> getUnavailablePhysicalIds();
};
template <class T>
void registerAvailCallback(const T *callback);
// Map camera_id -> status
- std::map<hidl_string, CameraStatus, CameraIdComparator> mDeviceStatusMap;
+ std::map<std::string, CameraStatus, CameraIdComparator> mDeviceStatusMap;
// For the singleton instance
static Mutex sLock;
- static CameraManagerGlobal* sInstance;
- CameraManagerGlobal() {};
- ~CameraManagerGlobal();
+ // Static instance is stored in a weak pointer, so will only exist if there is at least one
+ // active consumer of CameraManagerGlobal
+ static std::weak_ptr<CameraManagerGlobal> sInstance;
};
} // namespace acam;
@@ -259,7 +253,7 @@
*/
struct ACameraManager {
ACameraManager() :
- mGlobalManager(&(android::acam::CameraManagerGlobal::getInstance())) {}
+ mGlobalManager(android::acam::CameraManagerGlobal::getInstance()) {}
~ACameraManager();
camera_status_t getCameraIdList(ACameraIdList** cameraIdList);
static void deleteCameraIdList(ACameraIdList* cameraIdList);
@@ -277,7 +271,7 @@
kCameraIdListNotInit = -1
};
android::Mutex mLock;
- android::sp<android::acam::CameraManagerGlobal> mGlobalManager;
+ std::shared_ptr<android::acam::CameraManagerGlobal> mGlobalManager;
};
#endif //_ACAMERA_MANAGER_H
diff --git a/camera/ndk/ndk_vendor/impl/ACaptureRequestVendor.h b/camera/ndk/ndk_vendor/impl/ACaptureRequestVendor.h
index 5715d77..fcb7e34 100644
--- a/camera/ndk/ndk_vendor/impl/ACaptureRequestVendor.h
+++ b/camera/ndk/ndk_vendor/impl/ACaptureRequestVendor.h
@@ -16,6 +16,7 @@
#include "utils.h"
+using ::android::acam::utils::native_handle_ptr_wrapper;
struct ACameraOutputTarget {
explicit ACameraOutputTarget(const native_handle_t* window) : mWindow(window) {};
@@ -32,5 +33,5 @@
return mWindow > other.mWindow;
}
- android::acam::utils::native_handle_ptr_wrapper mWindow;
+ native_handle_ptr_wrapper mWindow;
};
diff --git a/camera/ndk/ndk_vendor/impl/utils.cpp b/camera/ndk/ndk_vendor/impl/utils.cpp
index e4fb204..73a527b 100644
--- a/camera/ndk/ndk_vendor/impl/utils.cpp
+++ b/camera/ndk/ndk_vendor/impl/utils.cpp
@@ -16,66 +16,75 @@
#define LOG_TAG "ACameraVendorUtils"
-#include <utils/Log.h>
-
#include "utils.h"
+#include <aidlcommonsupport/NativeHandle.h>
+#include <utils/Log.h>
+
namespace android {
namespace acam {
namespace utils {
-// Convert CaptureRequest wrappable by sp<> to hidl CaptureRequest.
-frameworks::cameraservice::device::V2_0::CaptureRequest
-convertToHidl(const CaptureRequest *captureRequest) {
- frameworks::cameraservice::device::V2_0::CaptureRequest hCaptureRequest;
- hCaptureRequest.physicalCameraSettings = captureRequest->mCaptureRequest.physicalCameraSettings;
- hCaptureRequest.streamAndWindowIds = captureRequest->mCaptureRequest.streamAndWindowIds;
- return hCaptureRequest;
+// Convert CaptureRequest wrappable by sp<> to aidl CaptureRequest.
+AidlCaptureRequest convertToAidl(const CaptureRequest *captureRequest) {
+ AidlCaptureRequest aidlCaptureRequest;
+ aidlCaptureRequest.physicalCameraSettings =
+ captureRequest->mCaptureRequest.physicalCameraSettings;
+ aidlCaptureRequest.streamAndWindowIds = captureRequest->mCaptureRequest.streamAndWindowIds;
+ return aidlCaptureRequest;
}
-HRotation convertToHidl(int rotation) {
- HRotation hRotation = HRotation::R0;
+OutputConfiguration::Rotation convertToAidl(int rotation) {
+ using AidlRotation = OutputConfiguration::Rotation;
+
+ AidlRotation aRot = AidlRotation ::R0;
switch(rotation) {
case CAMERA3_STREAM_ROTATION_90:
- hRotation = HRotation::R90;
+ aRot = AidlRotation::R90;
break;
case CAMERA3_STREAM_ROTATION_180:
- hRotation = HRotation::R180;
+ aRot = AidlRotation::R180;
break;
case CAMERA3_STREAM_ROTATION_270:
- hRotation = HRotation::R270;
+ aRot = AidlRotation::R270;
break;
default:
break;
}
- return hRotation;
+ return aRot;
}
-bool convertFromHidlCloned(const HCameraMetadata &metadata, CameraMetadata *rawMetadata) {
- const camera_metadata *buffer = (camera_metadata_t*)(metadata.data());
- size_t expectedSize = metadata.size();
+bool cloneFromAidl(const AidlCameraMetadata& srcMetadata, camera_metadata_t** dst) {
+ const camera_metadata *buffer = (camera_metadata_t*)(srcMetadata.metadata.data());
+ size_t expectedSize = srcMetadata.metadata.size();
int ret = validate_camera_metadata_structure(buffer, &expectedSize);
- if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
- *rawMetadata = buffer;
- } else {
- ALOGE("%s: Malformed camera metadata received from caller", __FUNCTION__);
+ if (ret != OK && ret != CAMERA_METADATA_VALIDATION_SHIFTED) {
+ ALOGE("%s: Malformed camera srcMetadata received from caller", __FUNCTION__);
return false;
}
- return true;
+
+ camera_metadata_t* clonedBuffer = clone_camera_metadata(buffer);
+ if (clonedBuffer != nullptr) {
+ *dst = clonedBuffer;
+ return true;
+ }
+
+ ALOGE("%s: Failed to clone srcMetadata buffer.", __FUNCTION__);
+ return false;
}
-// Note: existing data in dst will be gone. dst owns memory if shouldOwn is set
-// to true.
-void convertToHidl(const camera_metadata_t *src, HCameraMetadata* dst, bool shouldOwn) {
+// Note: existing data in dst will be gone.
+void convertToAidl(const camera_metadata_t *src, AidlCameraMetadata* dst) {
if (src == nullptr) {
return;
}
size_t size = get_camera_metadata_size(src);
- dst->setToExternal((uint8_t *) src, size, shouldOwn);
- return;
+ uint8_t* metadataStart = (uint8_t*)src;
+ uint8_t* metadataEnd = metadataStart + size;
+ dst->metadata.assign(metadataStart, metadataEnd);
}
-TemplateId convertToHidl(ACameraDevice_request_template templateId) {
+TemplateId convertToAidl(ACameraDevice_request_template templateId) {
switch(templateId) {
case TEMPLATE_STILL_CAPTURE:
return TemplateId::STILL_CAPTURE;
@@ -92,7 +101,7 @@
}
}
-camera_status_t convertFromHidl(Status status) {
+camera_status_t convertFromAidl(Status status) {
camera_status_t ret = ACAMERA_OK;
switch(status) {
case Status::NO_ERROR:
@@ -146,6 +155,14 @@
return true;
}
+bool isWindowNativeHandleEqual(const native_handle_t *nh1,
+ const aidl::android::hardware::common::NativeHandle& nh2) {
+ native_handle_t* tempNh = makeFromAidl(nh2);
+ bool equal = isWindowNativeHandleEqual(nh1, tempNh);
+ native_handle_delete(tempNh);
+ return equal;
+}
+
bool isWindowNativeHandleLessThan(const native_handle_t *nh1, const native_handle_t *nh2) {
if (isWindowNativeHandleEqual(nh1, nh2)) {
return false;
@@ -166,32 +183,6 @@
return !isWindowNativeHandleLessThan(nh1, nh2) && !isWindowNativeHandleEqual(nh1, nh2);
}
-bool areWindowNativeHandlesEqual(hidl_vec<hidl_handle> handles1, hidl_vec<hidl_handle> handles2) {
- if (handles1.size() != handles2.size()) {
- return false;
- }
- for (int i = 0; i < handles1.size(); i++) {
- if (!isWindowNativeHandleEqual(handles1[i], handles2[i])) {
- return false;
- }
- }
- return true;
-}
-
-bool areWindowNativeHandlesLessThan(hidl_vec<hidl_handle> handles1, hidl_vec<hidl_handle>handles2) {
- if (handles1.size() != handles2.size()) {
- return handles1.size() < handles2.size();
- }
- for (int i = 0; i < handles1.size(); i++) {
- const native_handle_t *handle1 = handles1[i].getNativeHandle();
- const native_handle_t *handle2 = handles2[i].getNativeHandle();
- if (!isWindowNativeHandleEqual(handle1, handle2)) {
- return isWindowNativeHandleLessThan(handle1, handle2);
- }
- }
- return false;
-}
-
} // namespace utils
} // namespace acam
} // namespace android
diff --git a/camera/ndk/ndk_vendor/impl/utils.h b/camera/ndk/ndk_vendor/impl/utils.h
index 62779a4..7ad74ad 100644
--- a/camera/ndk/ndk_vendor/impl/utils.h
+++ b/camera/ndk/ndk_vendor/impl/utils.h
@@ -14,46 +14,39 @@
* limitations under the License.
*/
-#include <android/frameworks/cameraservice/service/2.0/ICameraService.h>
-#include <android/frameworks/cameraservice/device/2.0/ICameraDeviceUser.h>
-#include <android/frameworks/cameraservice/device/2.0/types.h>
-#include <camera/NdkCameraDevice.h>
+#ifndef CAMERA_NDK_VENDOR_UTILS_H
+#define CAMERA_NDK_VENDOR_UTILS_H
+
#include <CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/device/CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureRequest.h>
+#include <aidl/android/frameworks/cameraservice/device/ICameraDeviceUser.h>
+#include <aidl/android/frameworks/cameraservice/device/OutputConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCameraSettings.h>
+#include <aidl/android/frameworks/cameraservice/device/TemplateId.h>
+#include <aidl/android/frameworks/cameraservice/service/ICameraService.h>
+#include <camera/NdkCameraDevice.h>
#include <hardware/camera3.h>
-
-#ifndef CAMERA_NDK_VENDOR_H
-#define CAMERA_NDK_VENDOR_H
-
-using android::hardware::hidl_vec;
-using android::hardware::hidl_handle;
+#include <utils/RefBase.h>
namespace android {
namespace acam {
namespace utils {
-using CameraMetadata = hardware::camera::common::V1_0::helper::CameraMetadata;
-using HCameraMetadata = frameworks::cameraservice::service::V2_0::CameraMetadata;
-using Status = frameworks::cameraservice::common::V2_0::Status;
-using TemplateId = frameworks::cameraservice::device::V2_0::TemplateId;
-using PhysicalCameraSettings = frameworks::cameraservice::device::V2_0::PhysicalCameraSettings;
-using HRotation = frameworks::cameraservice::device::V2_0::OutputConfiguration::Rotation;
-using OutputConfiguration = frameworks::cameraservice::device::V2_0::OutputConfiguration;
-
-// Utility class so that CaptureRequest can be stored by sp<>
-struct CaptureRequest : public RefBase {
- frameworks::cameraservice::device::V2_0::CaptureRequest mCaptureRequest;
- std::vector<const native_handle_t *> mSurfaceList;
- //Physical camera settings metadata is stored here, since the capture request
- //might not contain it. That's since, fmq might have consumed it.
- hidl_vec<PhysicalCameraSettings> mPhysicalCameraSettings;
-};
-
-bool areWindowNativeHandlesEqual(hidl_vec<hidl_handle> handles1, hidl_vec<hidl_handle>handles2);
-
-bool areWindowNativeHandlesLessThan(hidl_vec<hidl_handle> handles1, hidl_vec<hidl_handle>handles2);
+using ::aidl::android::frameworks::cameraservice::common::Status;
+using ::aidl::android::frameworks::cameraservice::device::OutputConfiguration;
+using ::aidl::android::frameworks::cameraservice::device::PhysicalCameraSettings;
+using ::aidl::android::frameworks::cameraservice::device::TemplateId;
+using ::aidl::android::hardware::common::NativeHandle;
+using ::android::hardware::camera::common::V1_0::helper::CameraMetadata;
+using AidlCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using AidlCaptureRequest = ::aidl::android::frameworks::cameraservice::device::CaptureRequest;
bool isWindowNativeHandleEqual(const native_handle_t *nh1, const native_handle_t *nh2);
+bool isWindowNativeHandleEqual(const native_handle_t* nh1, const NativeHandle& nh2);
+
bool isWindowNativeHandleLessThan(const native_handle_t *nh1, const native_handle_t *nh2);
// Convenience wrapper over isWindowNativeHandleLessThan and isWindowNativeHandleEqual
@@ -88,117 +81,30 @@
};
-// Wrapper around OutputConfiguration. This is needed since HIDL
-// OutputConfiguration is auto-generated and marked final. Therefore, operator
-// overloads outside the class, will not get picked by clang while trying to
-// store OutputConfiguration in maps/sets.
-struct OutputConfigurationWrapper {
- OutputConfiguration mOutputConfiguration;
-
- operator const OutputConfiguration &() const {
- return mOutputConfiguration;
- }
-
- OutputConfigurationWrapper() {
- mOutputConfiguration.rotation = OutputConfiguration::Rotation::R0;
- // The ndk currently doesn't support deferred surfaces
- mOutputConfiguration.isDeferred = false;
- mOutputConfiguration.width = 0;
- mOutputConfiguration.height = 0;
- // ndk doesn't support inter OutputConfiguration buffer sharing.
- mOutputConfiguration.windowGroupId = -1;
- };
-
- OutputConfigurationWrapper(const OutputConfigurationWrapper &other) {
- *this = other;
- }
-
- // Needed to make sure that OutputConfiguration in
- // OutputConfigurationWrapper, when copied doesn't call hidl_handle's
- // assignment operator / copy constructor, which will lead to native handle
- // cloning, which is not what we want for app callbacks which have the native
- // handle as parameter.
- OutputConfigurationWrapper &operator=(const OutputConfigurationWrapper &other) {
- const OutputConfiguration &outputConfiguration = other.mOutputConfiguration;
- mOutputConfiguration.rotation = outputConfiguration.rotation;
- mOutputConfiguration.isDeferred = outputConfiguration.isDeferred;
- mOutputConfiguration.width = outputConfiguration.width;
- mOutputConfiguration.height = outputConfiguration.height;
- mOutputConfiguration.windowGroupId = outputConfiguration.windowGroupId;
- mOutputConfiguration.windowHandles.resize(outputConfiguration.windowHandles.size());
- mOutputConfiguration.physicalCameraId = outputConfiguration.physicalCameraId;
- size_t i = 0;
- for (const auto &handle : outputConfiguration.windowHandles) {
- mOutputConfiguration.windowHandles[i++] = handle.getNativeHandle();
- }
- return *this;
- }
-
- bool operator ==(const OutputConfiguration &other) const {
- const OutputConfiguration &self = mOutputConfiguration;
- return self.rotation == other.rotation && self.windowGroupId == other.windowGroupId &&
- self.physicalCameraId == other.physicalCameraId && self.width == other.width &&
- self.height == other.height && self.isDeferred == other.isDeferred &&
- areWindowNativeHandlesEqual(self.windowHandles, other.windowHandles);
- }
-
- bool operator < (const OutputConfiguration &other) const {
- if (*this == other) {
- return false;
- }
- const OutputConfiguration &self = mOutputConfiguration;
- if (self.windowGroupId != other.windowGroupId) {
- return self.windowGroupId < other.windowGroupId;
- }
-
- if (self.width != other.width) {
- return self.width < other.width;
- }
-
- if (self.height != other.height) {
- return self.height < other.height;
- }
-
- if (self.rotation != other.rotation) {
- return static_cast<uint32_t>(self.rotation) < static_cast<uint32_t>(other.rotation);
- }
-
- if (self.isDeferred != other.isDeferred) {
- return self.isDeferred < other.isDeferred;
- }
-
- if (self.physicalCameraId != other.physicalCameraId) {
- return self.physicalCameraId < other.physicalCameraId;
- }
- return areWindowNativeHandlesLessThan(self.windowHandles, other.windowHandles);
- }
-
- bool operator != (const OutputConfiguration &other) const {
- return !(*this == other);
- }
-
- bool operator > (const OutputConfiguration &other) const {
- return (*this != other) && !(*this < other);
- }
+// Utility class so that CaptureRequest can be stored by sp<>
+struct CaptureRequest: public RefBase {
+ AidlCaptureRequest mCaptureRequest;
+ std::vector<native_handle_ptr_wrapper> mSurfaceList;
+ // Physical camera settings metadata is stored here, as the capture request
+ // might not contain it. That's since, fmq might have consumed it.
+ std::vector<PhysicalCameraSettings> mPhysicalCameraSettings;
};
-// Convert CaptureRequest wrappable by sp<> to hidl CaptureRequest.
-frameworks::cameraservice::device::V2_0::CaptureRequest convertToHidl(
- const CaptureRequest *captureRequest);
+AidlCaptureRequest convertToAidl(const CaptureRequest *captureRequest);
-HRotation convertToHidl(int rotation);
+OutputConfiguration::Rotation convertToAidl(int rotation);
-bool convertFromHidlCloned(const HCameraMetadata &metadata, CameraMetadata *rawMetadata);
+bool cloneFromAidl(const AidlCameraMetadata & srcMetadata, camera_metadata_t** dst);
// Note: existing data in dst will be gone.
-void convertToHidl(const camera_metadata_t *src, HCameraMetadata* dst, bool shouldOwn = false);
+void convertToAidl(const camera_metadata_t *src, AidlCameraMetadata * dst);
-TemplateId convertToHidl(ACameraDevice_request_template templateId);
+TemplateId convertToAidl(ACameraDevice_request_template templateId);
-camera_status_t convertFromHidl(Status status);
+camera_status_t convertFromAidl(Status status);
} // namespace utils
} // namespace acam
} // namespace android
-#endif // CAMERA_NDK_VENDOR_H
+#endif // CAMERA_NDK_VENDOR_UTILS_H
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 63cdb76..3a13a73 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -254,20 +254,22 @@
&mLogicalCaptureCallbacksV2, 1, &mStillRequest, &seqId);
}
- bool checkCallbacks(int pictureCount) {
+ bool checkCallbacks(int pictureCount, bool printLog = false) {
std::lock_guard<std::mutex> lock(mMutex);
if (mCompletedCaptureCallbackCount != pictureCount) {
- ALOGE("Completed capture callback count not as expected. expected %d actual %d",
- pictureCount, mCompletedCaptureCallbackCount);
+ ALOGE_IF(printLog,
+ "Completed capture callback count not as expected. expected %d actual %d",
+ pictureCount, mCompletedCaptureCallbackCount);
return false;
}
return true;
}
- bool checkCallbacksV2(int pictureCount) {
+ bool checkCallbacksV2(int pictureCount, bool printLog = false) {
std::lock_guard<std::mutex> lock(mMutex);
if (mCaptureStartedCallbackCount != pictureCount) {
- ALOGE("Capture started callback count not as expected. expected %d actual %d",
- pictureCount, mCaptureStartedCallbackCount);
+ ALOGE_IF(printLog,
+ "Capture started callback count not as expected. expected %d actual %d",
+ pictureCount, mCaptureStartedCallbackCount);
return false;
}
return true;
@@ -670,15 +672,22 @@
// Sleep until all capture finished
for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
usleep(kCaptureWaitUs);
- if (testCase.getAcquiredImageCount() == pictureCount) {
+ bool receivedAllCallbacks = v2 ? cameraHelper.checkCallbacksV2(pictureCount)
+ : cameraHelper.checkCallbacks(pictureCount);
+
+ bool acquiredAllImages = testCase.getAcquiredImageCount() == pictureCount;
+ if (acquiredAllImages) {
ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
pictureCount);
+ }
+ // Wait for all images to be acquired and all callbacks to be processed
+ if (acquiredAllImages && receivedAllCallbacks) {
break;
}
}
return testCase.getAcquiredImageCount() == pictureCount &&
- v2 ? cameraHelper.checkCallbacksV2(pictureCount) :
- cameraHelper.checkCallbacks(pictureCount);
+ v2 ? cameraHelper.checkCallbacksV2(pictureCount, /* printLog= */true) :
+ cameraHelper.checkCallbacks(pictureCount, /* printLog= */true);
}
bool testTakePicturesNative(const char* id) {
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index ea1ec0c..42e4717 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -53,6 +53,7 @@
using media::audio::common::AudioDeviceAddress;
using media::audio::common::AudioDeviceDescription;
using media::audio::common::AudioDeviceType;
+using media::audio::common::AudioDualMonoMode;
using media::audio::common::AudioEncapsulationMetadataType;
using media::audio::common::AudioEncapsulationMode;
using media::audio::common::AudioEncapsulationType;
@@ -63,9 +64,11 @@
using media::audio::common::AudioGainMode;
using media::audio::common::AudioInputFlags;
using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioLatencyMode;
using media::audio::common::AudioMode;
using media::audio::common::AudioOffloadInfo;
using media::audio::common::AudioOutputFlags;
+using media::audio::common::AudioPlaybackRate;
using media::audio::common::AudioPortDeviceExt;
using media::audio::common::AudioPortExt;
using media::audio::common::AudioPortMixExt;
@@ -2046,6 +2049,10 @@
return AUDIO_STANDARD_NONE;
case AudioStandard::EDID:
return AUDIO_STANDARD_EDID;
+ case AudioStandard::SADB:
+ return AUDIO_STANDARD_SADB;
+ case AudioStandard::VSADB:
+ return AUDIO_STANDARD_VSADB;
}
return unexpected(BAD_VALUE);
}
@@ -2057,6 +2064,10 @@
return AudioStandard::NONE;
case AUDIO_STANDARD_EDID:
return AudioStandard::EDID;
+ case AUDIO_STANDARD_SADB:
+ return AudioStandard::SADB;
+ case AUDIO_STANDARD_VSADB:
+ return AudioStandard::VSADB;
}
return unexpected(BAD_VALUE);
}
@@ -2123,6 +2134,139 @@
return unexpected(BAD_VALUE);
}
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(AudioDualMonoMode aidl) {
+ switch (aidl) {
+ case AudioDualMonoMode::OFF:
+ return AUDIO_DUAL_MONO_MODE_OFF;
+ case AudioDualMonoMode::LR:
+ return AUDIO_DUAL_MONO_MODE_LR;
+ case AudioDualMonoMode::LL:
+ return AUDIO_DUAL_MONO_MODE_LL;
+ case AudioDualMonoMode::RR:
+ return AUDIO_DUAL_MONO_MODE_RR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_DUAL_MONO_MODE_OFF:
+ return AudioDualMonoMode::OFF;
+ case AUDIO_DUAL_MONO_MODE_LR:
+ return AudioDualMonoMode::LR;
+ case AUDIO_DUAL_MONO_MODE_LL:
+ return AudioDualMonoMode::LL;
+ case AUDIO_DUAL_MONO_MODE_RR:
+ return AudioDualMonoMode::RR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ AudioPlaybackRate::TimestretchFallbackMode aidl) {
+ switch (aidl) {
+ case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT:
+ return AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT;
+ case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT:
+ return AUDIO_TIMESTRETCH_FALLBACK_DEFAULT;
+ case AudioPlaybackRate::TimestretchFallbackMode::MUTE:
+ return AUDIO_TIMESTRETCH_FALLBACK_MUTE;
+ case AudioPlaybackRate::TimestretchFallbackMode::FAIL:
+ return AUDIO_TIMESTRETCH_FALLBACK_FAIL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ audio_timestretch_fallback_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
+ return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT;
+ case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
+ return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT;
+ case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
+ return AudioPlaybackRate::TimestretchFallbackMode::MUTE;
+ case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
+ return AudioPlaybackRate::TimestretchFallbackMode::FAIL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+ AudioPlaybackRate::TimestretchMode aidl) {
+ switch (aidl) {
+ case AudioPlaybackRate::TimestretchMode::DEFAULT:
+ return AUDIO_TIMESTRETCH_STRETCH_DEFAULT;
+ case AudioPlaybackRate::TimestretchMode::VOICE:
+ return AUDIO_TIMESTRETCH_STRETCH_VOICE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+ audio_timestretch_stretch_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_TIMESTRETCH_STRETCH_DEFAULT:
+ return AudioPlaybackRate::TimestretchMode::DEFAULT;
+ case AUDIO_TIMESTRETCH_STRETCH_VOICE:
+ return AudioPlaybackRate::TimestretchMode::VOICE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const AudioPlaybackRate& aidl) {
+ audio_playback_rate_t legacy;
+ legacy.mSpeed = aidl.speed;
+ legacy.mPitch = aidl.pitch;
+ legacy.mFallbackMode = VALUE_OR_RETURN(
+ aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ aidl.fallbackMode));
+ legacy.mStretchMode = VALUE_OR_RETURN(
+ aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(aidl.timestretchMode));
+ return legacy;
+}
+
+ConversionResult<AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
+ AudioPlaybackRate aidl;
+ aidl.speed = legacy.mSpeed;
+ aidl.pitch = legacy.mPitch;
+ aidl.fallbackMode = VALUE_OR_RETURN(
+ legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ legacy.mFallbackMode));
+ aidl.timestretchMode = VALUE_OR_RETURN(
+ legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(legacy.mStretchMode));
+ return aidl;
+}
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(AudioLatencyMode aidl) {
+ switch (aidl) {
+ case AudioLatencyMode::FREE:
+ return AUDIO_LATENCY_MODE_FREE;
+ case AudioLatencyMode::LOW:
+ return AUDIO_LATENCY_MODE_LOW;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_LATENCY_MODE_FREE:
+ return AudioLatencyMode::FREE;
+ case AUDIO_LATENCY_MODE_LOW:
+ return AudioLatencyMode::LOW;
+ }
+ return unexpected(BAD_VALUE);
+}
+
} // namespace android
#if defined(BACKEND_NDK)
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
index e1efff9..c25ddb1 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
@@ -35,6 +35,7 @@
#include PREFIX(android/media/audio/common/AudioConfigBase.h)
#include PREFIX(android/media/audio/common/AudioContentType.h)
#include PREFIX(android/media/audio/common/AudioDeviceDescription.h)
+#include PREFIX(android/media/audio/common/AudioDualMonoMode.h)
#include PREFIX(android/media/audio/common/AudioEncapsulationMetadataType.h)
#include PREFIX(android/media/audio/common/AudioEncapsulationMode.h)
#include PREFIX(android/media/audio/common/AudioEncapsulationType.h)
@@ -44,11 +45,13 @@
#include PREFIX(android/media/audio/common/AudioGainMode.h)
#include PREFIX(android/media/audio/common/AudioInputFlags.h)
#include PREFIX(android/media/audio/common/AudioIoFlags.h)
+#include PREFIX(android/media/audio/common/AudioLatencyMode.h)
#include PREFIX(android/media/audio/common/AudioMode.h)
#include PREFIX(android/media/audio/common/AudioOffloadInfo.h)
#include PREFIX(android/media/audio/common/AudioOutputFlags.h)
#include PREFIX(android/media/audio/common/AudioPortExt.h)
#include PREFIX(android/media/audio/common/AudioPortMixExt.h)
+#include PREFIX(android/media/audio/common/AudioPlaybackRate.h)
#include PREFIX(android/media/audio/common/AudioProfile.h)
#include PREFIX(android/media/audio/common/AudioSource.h)
#include PREFIX(android/media/audio/common/AudioStandard.h)
@@ -287,8 +290,38 @@
ConversionResult<media::audio::common::AudioUuid> legacy2aidl_audio_uuid_t_AudioUuid(
const audio_uuid_t& legacy);
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::audio::common::AudioDualMonoMode aidl);
+ConversionResult<media::audio::common::AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ media::audio::common::AudioPlaybackRate::TimestretchFallbackMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ audio_timestretch_fallback_mode_t legacy);
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+ media::audio::common::AudioPlaybackRate::TimestretchMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+ audio_timestretch_stretch_mode_t legacy);
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(
+ const media::audio::common::AudioPlaybackRate& aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(media::audio::common::AudioLatencyMode aidl);
+ConversionResult<media::audio::common::AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy);
+
} // namespace android
#if defined(BACKEND_NDK)
} // aidl
-#endif
\ No newline at end of file
+#endif
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 1d8aea3..ba25226 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -80,6 +80,7 @@
"libbase",
"libdmabufheap",
"android.hardware.media.bufferpool@2.0",
+ "android.hardware.media.bufferpool2-V1-ndk",
],
local_include_dirs: [
@@ -94,8 +95,12 @@
shared_libs: [
"android.hardware.graphics.bufferqueue@2.0",
"android.hardware.graphics.common@1.2",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
"android.hardware.media.bufferpool@2.0",
+ "android.hardware.media.bufferpool2-V1-ndk",
"libbase",
+ "libbinder_ndk",
"libcutils",
"libdl",
"libdmabufheap",
@@ -107,6 +112,7 @@
"libnativewindow",
"libstagefright_foundation",
"libstagefright_bufferpool@2.0.1",
+ "libstagefright_aidl_bufferpool2",
"libui",
"libutils",
],
@@ -135,6 +141,7 @@
"libnativewindow",
"libcodec2_soft_common",
"libsfplugin_ccodec_utils",
+ "libstagefright_aidl_bufferpool2",
"libstagefright_foundation",
"libstagefright_bufferpool@2.0.1",
"libgralloctypes",
@@ -144,9 +151,13 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
+ "android.hardware.media.bufferpool2-V1-ndk",
],
shared_libs: [
+ "libbinder_ndk",
"libui",
"libdl",
"libvndksupport",
diff --git a/media/codec2/vndk/C2Buffer.cpp b/media/codec2/vndk/C2Buffer.cpp
index 143355f..018e269 100644
--- a/media/codec2/vndk/C2Buffer.cpp
+++ b/media/codec2/vndk/C2Buffer.cpp
@@ -29,19 +29,21 @@
#include <C2BlockInternal.h>
#include <C2PlatformSupport.h>
#include <bufferpool/ClientManager.h>
+#include <bufferpool2/ClientManager.h>
namespace {
using android::C2AllocatorBlob;
using android::C2AllocatorGralloc;
using android::C2AllocatorIon;
-using android::hardware::media::bufferpool::BufferPoolData;
+
+namespace bufferpool = android::hardware::media::bufferpool;
+namespace bufferpool_impl = android::hardware::media::bufferpool::V2_0::implementation;
using android::hardware::media::bufferpool::V2_0::ResultStatus;
-using android::hardware::media::bufferpool::V2_0::implementation::BufferPoolAllocation;
-using android::hardware::media::bufferpool::V2_0::implementation::BufferPoolAllocator;
-using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
-using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
-using android::hardware::media::bufferpool::V2_0::implementation::INVALID_CONNECTIONID;
+
+namespace bufferpool2 = aidl::android::hardware::media::bufferpool2;
+namespace bufferpool2_impl = aidl::android::hardware::media::bufferpool2::implementation;
+using ResultStatus2 = aidl::android::hardware::media::bufferpool2::ResultStatus;
// This anonymous namespace contains the helper classes that allow our implementation to create
// block/buffer objects.
@@ -354,21 +356,21 @@
return TYPE_BUFFERPOOL;
}
- void getBufferPoolData(std::shared_ptr<BufferPoolData> *data) const {
+ void getBufferPoolData(std::shared_ptr<bufferpool::BufferPoolData> *data) const {
*data = mData;
}
- C2PooledBlockPoolData(const std::shared_ptr<BufferPoolData> &data) : mData(data) {}
+ C2PooledBlockPoolData(const std::shared_ptr<bufferpool::BufferPoolData> &data) : mData(data) {}
virtual ~C2PooledBlockPoolData() override {}
private:
- std::shared_ptr<BufferPoolData> mData;
+ std::shared_ptr<bufferpool::BufferPoolData> mData;
};
bool _C2BlockFactory::GetBufferPoolData(
const std::shared_ptr<const _C2BlockPoolData> &data,
- std::shared_ptr<BufferPoolData> *bufferPoolData) {
+ std::shared_ptr<bufferpool::BufferPoolData> *bufferPoolData) {
if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERPOOL) {
const std::shared_ptr<const C2PooledBlockPoolData> poolData =
std::static_pointer_cast<const C2PooledBlockPoolData>(data);
@@ -378,6 +380,37 @@
return false;
}
+struct C2_HIDE C2PooledBlockPoolData2 : _C2BlockPoolData { // AIDL BufferPool(bufferpool2)
+
+ type_t getType() const override {
+ return TYPE_BUFFERPOOL2;
+ }
+
+ void getBufferPoolData(std::shared_ptr<bufferpool2::BufferPoolData> *data) const {
+ *data = mData;
+ }
+
+ C2PooledBlockPoolData2(const std::shared_ptr<bufferpool2::BufferPoolData> &data)
+ : mData(data) {}
+
+ virtual ~C2PooledBlockPoolData2() override {}
+
+private:
+ std::shared_ptr<bufferpool2::BufferPoolData> mData;
+};
+
+bool _C2BlockFactory::GetBufferPoolData(
+ const std::shared_ptr<const _C2BlockPoolData> &data,
+ std::shared_ptr<bufferpool2::BufferPoolData> *bufferPoolData) {
+ if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERPOOL2) {
+ const std::shared_ptr<const C2PooledBlockPoolData2> poolData =
+ std::static_pointer_cast<const C2PooledBlockPoolData2>(data);
+ poolData->getBufferPoolData(bufferPoolData);
+ return true;
+ }
+ return false;
+}
+
std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
const std::shared_ptr<C2LinearAllocation> &alloc,
const std::shared_ptr<_C2BlockPoolData> &data, size_t offset, size_t size) {
@@ -422,7 +455,7 @@
}
std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
- const C2Handle *cHandle, const std::shared_ptr<BufferPoolData> &data) {
+ const C2Handle *cHandle, const std::shared_ptr<bufferpool::BufferPoolData> &data) {
// TODO: get proper allocator? and mutex?
static std::shared_ptr<C2Allocator> sAllocator = []{
std::shared_ptr<C2Allocator> allocator;
@@ -452,11 +485,43 @@
return nullptr;
};
+std::shared_ptr<C2LinearBlock> _C2BlockFactory::CreateLinearBlock(
+ const C2Handle *cHandle, const std::shared_ptr<bufferpool2::BufferPoolData> &data) {
+ // TODO: get proper allocator? and mutex?
+ static std::shared_ptr<C2Allocator> sAllocator = []{
+ std::shared_ptr<C2Allocator> allocator;
+ std::shared_ptr<C2AllocatorStore> allocatorStore =
+ android::GetCodec2PlatformAllocatorStore();
+ allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+
+ return allocator;
+ }();
+
+ if (sAllocator == nullptr)
+ return nullptr;
+
+ bool isValidHandle = sAllocator->checkHandle(cHandle);
+
+ std::shared_ptr<C2LinearAllocation> alloc;
+ if (isValidHandle) {
+ c2_status_t err = sAllocator->priorLinearAllocation(cHandle, &alloc);
+ const std::shared_ptr<C2PooledBlockPoolData2> poolData =
+ std::make_shared<C2PooledBlockPoolData2>(data);
+ if (err == C2_OK && poolData) {
+ // TODO: config params?
+ std::shared_ptr<C2LinearBlock> block =
+ _C2BlockFactory::CreateLinearBlock(alloc, poolData);
+ return block;
+ }
+ }
+ return nullptr;
+};
+
/**
* Wrapped C2Allocator which is injected to buffer pool on behalf of
* C2BlockPool.
*/
-class _C2BufferPoolAllocator : public BufferPoolAllocator {
+class _C2BufferPoolAllocator : public bufferpool_impl::BufferPoolAllocator {
public:
_C2BufferPoolAllocator(const std::shared_ptr<C2Allocator> &allocator)
: mAllocator(allocator) {}
@@ -464,7 +529,7 @@
~_C2BufferPoolAllocator() override {}
ResultStatus allocate(const std::vector<uint8_t> ¶ms,
- std::shared_ptr<BufferPoolAllocation> *alloc,
+ std::shared_ptr<bufferpool_impl::BufferPoolAllocation> *alloc,
size_t *allocSize) override;
bool compatible(const std::vector<uint8_t> &newParams,
@@ -496,7 +561,7 @@
std::vector<uint8_t> *params);
/**
- * Transforms an existing native handle to an C2LinearAllcation.
+ * Transforms an existing native handle to a C2LinearAllocation.
* Wrapper to C2Allocator#priorLinearAllocation
*/
c2_status_t priorLinearAllocation(
@@ -504,7 +569,7 @@
std::shared_ptr<C2LinearAllocation> *c2Allocation);
/**
- * Transforms an existing native handle to an C2GraphicAllcation.
+ * Transforms an existing native handle to a C2GraphicAllocation.
* Wrapper to C2Allocator#priorGraphicAllocation
*/
c2_status_t priorGraphicAllocation(
@@ -545,7 +610,7 @@
LinearAllocationDtor(const std::shared_ptr<C2LinearAllocation> &alloc)
: mAllocation(alloc) {}
- void operator()(BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
+ void operator()(bufferpool_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
const std::shared_ptr<C2LinearAllocation> mAllocation;
};
@@ -554,14 +619,14 @@
GraphicAllocationDtor(const std::shared_ptr<C2GraphicAllocation> &alloc)
: mAllocation(alloc) {}
- void operator()(BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
+ void operator()(bufferpool_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
const std::shared_ptr<C2GraphicAllocation> mAllocation;
};
ResultStatus _C2BufferPoolAllocator::allocate(
const std::vector<uint8_t> ¶ms,
- std::shared_ptr<BufferPoolAllocation> *alloc,
+ std::shared_ptr<bufferpool_impl::BufferPoolAllocation> *alloc,
size_t *allocSize) {
AllocParams c2Params;
memcpy(&c2Params, params.data(), std::min(sizeof(AllocParams), params.size()));
@@ -574,9 +639,10 @@
status = mAllocator->newLinearAllocation(
c2Params.data.params[0], c2Params.data.usage, &c2Linear);
if (status == C2_OK && c2Linear) {
- BufferPoolAllocation *ptr = new BufferPoolAllocation(c2Linear->handle());
+ bufferpool_impl::BufferPoolAllocation *ptr =
+ new bufferpool_impl::BufferPoolAllocation(c2Linear->handle());
if (ptr) {
- *alloc = std::shared_ptr<BufferPoolAllocation>(
+ *alloc = std::shared_ptr<bufferpool_impl::BufferPoolAllocation>(
ptr, LinearAllocationDtor(c2Linear));
if (*alloc) {
*allocSize = (size_t)c2Params.data.params[0];
@@ -596,9 +662,10 @@
c2Params.data.params[2],
c2Params.data.usage, &c2Graphic);
if (status == C2_OK && c2Graphic) {
- BufferPoolAllocation *ptr = new BufferPoolAllocation(c2Graphic->handle());
+ bufferpool_impl::BufferPoolAllocation *ptr =
+ new bufferpool_impl::BufferPoolAllocation(c2Graphic->handle());
if (ptr) {
- *alloc = std::shared_ptr<BufferPoolAllocation>(
+ *alloc = std::shared_ptr<bufferpool_impl::BufferPoolAllocation>(
ptr, GraphicAllocationDtor(c2Graphic));
if (*alloc) {
*allocSize = c2Params.data.params[0] * c2Params.data.params[1];
@@ -624,7 +691,7 @@
memcpy(&newAlloc, newParams.data(), std::min(sizeof(AllocParams), newParams.size()));
memcpy(&oldAlloc, oldParams.data(), std::min(sizeof(AllocParams), oldParams.size()));
- // TODO: support not exact matching. e.g) newCapacity < oldCapacity
+ // TODO: support not exact matching. e.g.) newCapacity < oldCapacity
if (newAlloc.data.allocType == oldAlloc.data.allocType &&
newAlloc.data.usage.expected == oldAlloc.data.usage.expected) {
for (int i = 0; i < kMaxIntParams; ++i) {
@@ -666,7 +733,7 @@
public:
Impl(const std::shared_ptr<C2Allocator> &allocator)
: mInit(C2_OK),
- mBufferPoolManager(ClientManager::getInstance()),
+ mBufferPoolManager(bufferpool_impl::ClientManager::getInstance()),
mAllocator(std::make_shared<_C2BufferPoolAllocator>(allocator)) {
if (mAllocator && mBufferPoolManager) {
if (mBufferPoolManager->create(
@@ -692,7 +759,7 @@
}
std::vector<uint8_t> params;
mAllocator->getLinearParams(capacity, usage, ¶ms);
- std::shared_ptr<BufferPoolData> bufferPoolData;
+ std::shared_ptr<bufferpool::BufferPoolData> bufferPoolData;
native_handle_t *cHandle = nullptr;
ResultStatus status = mBufferPoolManager->allocate(
mConnectionId, params, &cHandle, &bufferPoolData);
@@ -725,7 +792,7 @@
}
std::vector<uint8_t> params;
mAllocator->getGraphicParams(width, height, format, usage, ¶ms);
- std::shared_ptr<BufferPoolData> bufferPoolData;
+ std::shared_ptr<bufferpool::BufferPoolData> bufferPoolData;
native_handle_t *cHandle = nullptr;
ResultStatus status = mBufferPoolManager->allocate(
mConnectionId, params, &cHandle, &bufferPoolData);
@@ -750,20 +817,340 @@
return C2_CORRUPTED;
}
- ConnectionId getConnectionId() {
- return mInit != C2_OK ? INVALID_CONNECTIONID : mConnectionId;
+ bufferpool_impl::ConnectionId getConnectionId() {
+ return mInit != C2_OK ? bufferpool_impl::INVALID_CONNECTIONID : mConnectionId;
}
private:
c2_status_t mInit;
- const android::sp<ClientManager> mBufferPoolManager;
- ConnectionId mConnectionId; // locally
+ const android::sp<bufferpool_impl::ClientManager> mBufferPoolManager;
+ bufferpool_impl::ConnectionId mConnectionId; // locally
const std::shared_ptr<_C2BufferPoolAllocator> mAllocator;
};
+/**
+ * Wrapped C2Allocator which is injected to AIDL buffer pool on behalf of
+ * C2BlockPool.
+ */
+class _C2BufferPoolAllocator2 : public bufferpool2_impl::BufferPoolAllocator {
+public:
+ _C2BufferPoolAllocator2(const std::shared_ptr<C2Allocator> &allocator)
+ : mAllocator(allocator) {}
+
+ ~_C2BufferPoolAllocator2() override {}
+
+ bufferpool2_impl::BufferPoolStatus allocate(const std::vector<uint8_t> ¶ms,
+ std::shared_ptr<bufferpool2_impl::BufferPoolAllocation> *alloc,
+ size_t *allocSize) override;
+
+ bool compatible(const std::vector<uint8_t> &newParams,
+ const std::vector<uint8_t> &oldParams) override;
+
+ // Methods for codec2 component (C2BlockPool).
+ /**
+ * Transforms linear allocation parameters for C2Allocator to parameters
+ * for buffer pool.
+ *
+ * @param capacity size of linear allocation
+ * @param usage memory usage pattern for linear allocation
+ * @param params allocation parameters for buffer pool
+ */
+ void getLinearParams(uint32_t capacity, C2MemoryUsage usage,
+ std::vector<uint8_t> *params);
+
+ /**
+ * Transforms graphic allocation parameters for C2Allocator to parameters
+ * for buffer pool.
+ *
+ * @param width width of graphic allocation
+ * @param height height of graphic allocation
+ * @param format color format of graphic allocation
+ * @param params allocation parameter for buffer pool
+ */
+ void getGraphicParams(uint32_t width, uint32_t height,
+ uint32_t format, C2MemoryUsage usage,
+ std::vector<uint8_t> *params);
+
+ /**
+ * Transforms an existing native handle to a C2LinearAllocation.
+ * Wrapper to C2Allocator#priorLinearAllocation
+ */
+ c2_status_t priorLinearAllocation(
+ const C2Handle *handle,
+ std::shared_ptr<C2LinearAllocation> *c2Allocation);
+
+ /**
+ * Transforms an existing native handle to a C2GraphicAllocation.
+ * Wrapper to C2Allocator#priorGraphicAllocation
+ */
+ c2_status_t priorGraphicAllocation(
+ const C2Handle *handle,
+ std::shared_ptr<C2GraphicAllocation> *c2Allocation);
+
+private:
+ static constexpr int kMaxIntParams = 5; // large enough number;
+
+ enum AllocType : uint8_t {
+ ALLOC_NONE = 0,
+
+ ALLOC_LINEAR,
+ ALLOC_GRAPHIC,
+ };
+
+ union AllocParams {
+ struct {
+ AllocType allocType;
+ C2MemoryUsage usage;
+ uint32_t params[kMaxIntParams];
+ } data;
+ uint8_t array[0];
+
+ AllocParams() : data{ALLOC_NONE, {0, 0}, {0}} {}
+ AllocParams(C2MemoryUsage usage, uint32_t capacity)
+ : data{ALLOC_LINEAR, usage, {[0] = capacity}} {}
+ AllocParams(
+ C2MemoryUsage usage,
+ uint32_t width, uint32_t height, uint32_t format)
+ : data{ALLOC_GRAPHIC, usage, {width, height, format}} {}
+ };
+
+ const std::shared_ptr<C2Allocator> mAllocator;
+};
+
+struct LinearAllocationDtor2 {
+ LinearAllocationDtor2(const std::shared_ptr<C2LinearAllocation> &alloc)
+ : mAllocation(alloc) {}
+
+ void operator()(bufferpool2_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
+
+ const std::shared_ptr<C2LinearAllocation> mAllocation;
+};
+
+struct GraphicAllocationDtor2 {
+ GraphicAllocationDtor2(const std::shared_ptr<C2GraphicAllocation> &alloc)
+ : mAllocation(alloc) {}
+
+ void operator()(bufferpool2_impl::BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
+
+ const std::shared_ptr<C2GraphicAllocation> mAllocation;
+};
+
+bufferpool2_impl::BufferPoolStatus _C2BufferPoolAllocator2::allocate(
+ const std::vector<uint8_t> ¶ms,
+ std::shared_ptr<bufferpool2_impl::BufferPoolAllocation> *alloc,
+ size_t *allocSize) {
+ AllocParams c2Params;
+ memcpy(&c2Params, params.data(), std::min(sizeof(AllocParams), params.size()));
+ c2_status_t status = C2_BAD_VALUE;
+ switch(c2Params.data.allocType) {
+ case ALLOC_NONE:
+ break;
+ case ALLOC_LINEAR: {
+ std::shared_ptr<C2LinearAllocation> c2Linear;
+ status = mAllocator->newLinearAllocation(
+ c2Params.data.params[0], c2Params.data.usage, &c2Linear);
+ if (status == C2_OK && c2Linear) {
+ bufferpool2_impl::BufferPoolAllocation *ptr =
+ new bufferpool2_impl::BufferPoolAllocation(c2Linear->handle());
+ if (ptr) {
+ *alloc = std::shared_ptr<bufferpool2_impl::BufferPoolAllocation>(
+ ptr, LinearAllocationDtor2(c2Linear));
+ if (*alloc) {
+ *allocSize = (size_t)c2Params.data.params[0];
+ return ResultStatus2::OK;
+ }
+ delete ptr;
+ }
+ return ResultStatus2::NO_MEMORY;
+ }
+ break;
+ }
+ case ALLOC_GRAPHIC: {
+ std::shared_ptr<C2GraphicAllocation> c2Graphic;
+ status = mAllocator->newGraphicAllocation(
+ c2Params.data.params[0],
+ c2Params.data.params[1],
+ c2Params.data.params[2],
+ c2Params.data.usage, &c2Graphic);
+ if (status == C2_OK && c2Graphic) {
+ bufferpool2_impl::BufferPoolAllocation *ptr =
+ new bufferpool2_impl::BufferPoolAllocation(c2Graphic->handle());
+ if (ptr) {
+ *alloc = std::shared_ptr<bufferpool2_impl::BufferPoolAllocation>(
+ ptr, GraphicAllocationDtor2(c2Graphic));
+ if (*alloc) {
+ *allocSize = c2Params.data.params[0] * c2Params.data.params[1];
+ return ResultStatus2::OK;
+ }
+ delete ptr;
+ }
+ return ResultStatus2::NO_MEMORY;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return ResultStatus2::CRITICAL_ERROR;
+}
+
+bool _C2BufferPoolAllocator2::compatible(
+ const std::vector<uint8_t> &newParams,
+ const std::vector<uint8_t> &oldParams) {
+ AllocParams newAlloc;
+ AllocParams oldAlloc;
+ memcpy(&newAlloc, newParams.data(), std::min(sizeof(AllocParams), newParams.size()));
+ memcpy(&oldAlloc, oldParams.data(), std::min(sizeof(AllocParams), oldParams.size()));
+
+ // TODO: support not exact matching. e.g.) newCapacity < oldCapacity
+ if (newAlloc.data.allocType == oldAlloc.data.allocType &&
+ newAlloc.data.usage.expected == oldAlloc.data.usage.expected) {
+ for (int i = 0; i < kMaxIntParams; ++i) {
+ if (newAlloc.data.params[i] != oldAlloc.data.params[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+void _C2BufferPoolAllocator2::getLinearParams(
+ uint32_t capacity, C2MemoryUsage usage, std::vector<uint8_t> *params) {
+ AllocParams c2Params(usage, capacity);
+ params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
+}
+
+void _C2BufferPoolAllocator2::getGraphicParams(
+ uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
+ std::vector<uint8_t> *params) {
+ AllocParams c2Params(usage, width, height, format);
+ params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
+}
+
+c2_status_t _C2BufferPoolAllocator2::priorLinearAllocation(
+ const C2Handle *handle,
+ std::shared_ptr<C2LinearAllocation> *c2Allocation) {
+ return mAllocator->priorLinearAllocation(handle, c2Allocation);
+}
+
+c2_status_t _C2BufferPoolAllocator2::priorGraphicAllocation(
+ const C2Handle *handle,
+ std::shared_ptr<C2GraphicAllocation> *c2Allocation) {
+ return mAllocator->priorGraphicAllocation(handle, c2Allocation);
+}
+
+class C2PooledBlockPool::Impl2 {
+public:
+ Impl2(const std::shared_ptr<C2Allocator> &allocator)
+ : mInit(C2_OK),
+ mBufferPoolManager(bufferpool2_impl::ClientManager::getInstance()),
+ mAllocator(std::make_shared<_C2BufferPoolAllocator2>(allocator)) {
+ if (mAllocator && mBufferPoolManager) {
+ if (mBufferPoolManager->create(
+ mAllocator, &mConnectionId) == ResultStatus2::OK) {
+ return;
+ }
+ }
+ mInit = C2_NO_INIT;
+ }
+
+ ~Impl2() {
+ if (mInit == C2_OK) {
+ mBufferPoolManager->close(mConnectionId);
+ }
+ }
+
+ c2_status_t fetchLinearBlock(
+ uint32_t capacity, C2MemoryUsage usage,
+ std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
+ block->reset();
+ if (mInit != C2_OK) {
+ return mInit;
+ }
+ std::vector<uint8_t> params;
+ mAllocator->getLinearParams(capacity, usage, ¶ms);
+ std::shared_ptr<bufferpool2::BufferPoolData> bufferPoolData;
+ native_handle_t *cHandle = nullptr;
+ bufferpool2_impl::BufferPoolStatus status = mBufferPoolManager->allocate(
+ mConnectionId, params, &cHandle, &bufferPoolData);
+ if (status == ResultStatus2::OK) {
+ std::shared_ptr<C2LinearAllocation> alloc;
+ std::shared_ptr<C2PooledBlockPoolData2> poolData =
+ std::make_shared<C2PooledBlockPoolData2>(bufferPoolData);
+ c2_status_t err = mAllocator->priorLinearAllocation(cHandle, &alloc);
+ if (err == C2_OK && poolData && alloc) {
+ *block = _C2BlockFactory::CreateLinearBlock(alloc, poolData, 0, capacity);
+ if (*block) {
+ return C2_OK;
+ }
+ }
+ return C2_NO_MEMORY;
+ }
+ if (status == ResultStatus2::NO_MEMORY) {
+ return C2_NO_MEMORY;
+ }
+ return C2_CORRUPTED;
+ }
+
+ c2_status_t fetchGraphicBlock(
+ uint32_t width, uint32_t height, uint32_t format,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2GraphicBlock> *block) {
+ block->reset();
+ if (mInit != C2_OK) {
+ return mInit;
+ }
+ std::vector<uint8_t> params;
+ mAllocator->getGraphicParams(width, height, format, usage, ¶ms);
+ std::shared_ptr<bufferpool2::BufferPoolData> bufferPoolData;
+ native_handle_t *cHandle = nullptr;
+ bufferpool2_impl::BufferPoolStatus status = mBufferPoolManager->allocate(
+ mConnectionId, params, &cHandle, &bufferPoolData);
+ if (status == ResultStatus2::OK) {
+ std::shared_ptr<C2GraphicAllocation> alloc;
+ std::shared_ptr<C2PooledBlockPoolData2> poolData =
+ std::make_shared<C2PooledBlockPoolData2>(bufferPoolData);
+ c2_status_t err = mAllocator->priorGraphicAllocation(
+ cHandle, &alloc);
+ if (err == C2_OK && poolData && alloc) {
+ *block = _C2BlockFactory::CreateGraphicBlock(
+ alloc, poolData, C2Rect(width, height));
+ if (*block) {
+ return C2_OK;
+ }
+ }
+ return C2_NO_MEMORY;
+ }
+ if (status == ResultStatus2::NO_MEMORY) {
+ return C2_NO_MEMORY;
+ }
+ return C2_CORRUPTED;
+ }
+
+ bufferpool2_impl::ConnectionId getConnectionId() {
+ return mInit != C2_OK ? bufferpool2_impl::INVALID_CONNECTIONID : mConnectionId;
+ }
+
+private:
+ c2_status_t mInit;
+ const std::shared_ptr<bufferpool2_impl::ClientManager> mBufferPoolManager;
+ bufferpool2_impl::ConnectionId mConnectionId; // locally
+ const std::shared_ptr<_C2BufferPoolAllocator2> mAllocator;
+};
+
C2PooledBlockPool::C2PooledBlockPool(
- const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId)
- : mAllocator(allocator), mLocalId(localId), mImpl(new Impl(allocator)) {}
+ const std::shared_ptr<C2Allocator> &allocator,
+ const local_id_t localId,
+ BufferPoolVer ver)
+ : mAllocator(allocator), mLocalId(localId), mBufferPoolVer(ver) {
+ if (mBufferPoolVer == VER_HIDL) {
+ mImpl = std::make_unique<Impl>(allocator);
+ }
+ if (mBufferPoolVer == VER_AIDL2) {
+ mImpl2 = std::make_unique<Impl2>(allocator);
+ }
+ }
C2PooledBlockPool::~C2PooledBlockPool() {
}
@@ -772,9 +1159,12 @@
uint32_t capacity,
C2MemoryUsage usage,
std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
- if (mImpl) {
+ if (mBufferPoolVer == VER_HIDL && mImpl) {
return mImpl->fetchLinearBlock(capacity, usage, block);
}
+ if (mBufferPoolVer == VER_AIDL2 && mImpl2) {
+ return mImpl2->fetchLinearBlock(capacity, usage, block);
+ }
return C2_CORRUPTED;
}
@@ -784,16 +1174,22 @@
uint32_t format,
C2MemoryUsage usage,
std::shared_ptr<C2GraphicBlock> *block) {
- if (mImpl) {
+ if (mBufferPoolVer == VER_HIDL && mImpl) {
return mImpl->fetchGraphicBlock(width, height, format, usage, block);
}
+ if (mBufferPoolVer == VER_AIDL2 && mImpl2) {
+ return mImpl2->fetchGraphicBlock(width, height, format, usage, block);
+ }
return C2_CORRUPTED;
}
int64_t C2PooledBlockPool::getConnectionId() {
- if (mImpl) {
+ if (mBufferPoolVer == VER_HIDL && mImpl) {
return mImpl->getConnectionId();
}
+ if (mBufferPoolVer == VER_AIDL2 && mImpl2) {
+ return mImpl2->getConnectionId();
+ }
return 0;
}
@@ -1128,7 +1524,7 @@
std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
const C2Handle *cHandle,
- const std::shared_ptr<BufferPoolData> &data) {
+ const std::shared_ptr<bufferpool::BufferPoolData> &data) {
// TODO: get proper allocator? and mutex?
static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
@@ -1147,6 +1543,26 @@
return nullptr;
};
+std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
+ const C2Handle *cHandle,
+ const std::shared_ptr<bufferpool2::BufferPoolData> &data) {
+ // TODO: get proper allocator? and mutex?
+ static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
+
+ std::shared_ptr<C2GraphicAllocation> alloc;
+ if (sAllocator->isValid(cHandle)) {
+ c2_status_t err = sAllocator->priorGraphicAllocation(cHandle, &alloc);
+ const std::shared_ptr<C2PooledBlockPoolData2> poolData =
+ std::make_shared<C2PooledBlockPoolData2>(data);
+ if (err == C2_OK && poolData) {
+ // TODO: config setup?
+ std::shared_ptr<C2GraphicBlock> block =
+ _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
+ return block;
+ }
+ }
+ return nullptr;
+};
/* ========================================== BUFFER ========================================= */
diff --git a/media/codec2/vndk/include/C2BufferPriv.h b/media/codec2/vndk/include/C2BufferPriv.h
index be5f69c..527845f 100644
--- a/media/codec2/vndk/include/C2BufferPriv.h
+++ b/media/codec2/vndk/include/C2BufferPriv.h
@@ -74,7 +74,14 @@
class C2PooledBlockPool : public C2BlockPool {
public:
- C2PooledBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId);
+ enum BufferPoolVer : int {
+ VER_HIDL = 0,
+ VER_AIDL2
+ };
+ C2PooledBlockPool(
+ const std::shared_ptr<C2Allocator> &allocator,
+ const local_id_t localId,
+ BufferPoolVer ver = VER_HIDL);
virtual ~C2PooledBlockPool() override;
@@ -117,9 +124,12 @@
private:
const std::shared_ptr<C2Allocator> mAllocator;
const local_id_t mLocalId;
+ const BufferPoolVer mBufferPoolVer;
- class Impl;
+ class Impl; // HIDL BufferPool VER_HIDL
std::unique_ptr<Impl> mImpl;
+ class Impl2; // AIDL BufferPool(bufferpool2) VER_AIDL2
+ std::unique_ptr<Impl2> mImpl2;
};
#endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index c510fca..fe5390a 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -21,17 +21,22 @@
#include <C2Buffer.h>
-namespace android {
-namespace hardware {
-namespace media {
-namespace bufferpool {
+// Note: HIDL-BufferPool and AIDL-BufferPool are not compatible
+namespace android::hardware::media::bufferpool {
+// BuffePool Data for HIDL-BufferPool
struct BufferPoolData;
}
+namespace aidl::android::hardware::media::bufferpool2 {
+
+// BuffePool Data for AIDL-BufferPool
+struct BufferPoolData;
+
}
-}
-}
+
+using bufferpool_BufferPoolData = android::hardware::media::bufferpool::BufferPoolData;
+using bufferpool2_BufferPoolData = aidl::android::hardware::media::bufferpool2::BufferPoolData;
/**
* Stores informations from C2BlockPool implementations which are required by C2Block.
@@ -40,6 +45,7 @@
enum type_t : int {
TYPE_BUFFERPOOL = 0,
TYPE_BUFFERQUEUE,
+ TYPE_BUFFERPOOL2, // AIDL-BufferPool
};
virtual type_t getType() const = 0;
@@ -136,6 +142,7 @@
std::shared_ptr<C2GraphicBlock> CreateGraphicBlock(
const C2Handle *handle);
+ // HIDL-BufferPool
/**
* Create a linear block from the received bufferpool data.
*
@@ -147,7 +154,7 @@
static
std::shared_ptr<C2LinearBlock> CreateLinearBlock(
const C2Handle *handle,
- const std::shared_ptr<android::hardware::media::bufferpool::BufferPoolData> &data);
+ const std::shared_ptr<bufferpool_BufferPoolData> &data);
/**
* Create a graphic block from the received bufferpool data.
@@ -160,7 +167,7 @@
static
std::shared_ptr<C2GraphicBlock> CreateGraphicBlock(
const C2Handle *handle,
- const std::shared_ptr<android::hardware::media::bufferpool::BufferPoolData> &data);
+ const std::shared_ptr<bufferpool_BufferPoolData> &data);
/**
* Get bufferpool data from the blockpool data.
@@ -174,7 +181,48 @@
static
bool GetBufferPoolData(
const std::shared_ptr<const _C2BlockPoolData> &poolData,
- std::shared_ptr<android::hardware::media::bufferpool::BufferPoolData> *bufferPoolData);
+ std::shared_ptr<bufferpool_BufferPoolData> *bufferPoolData);
+
+ // AIDL-BufferPool
+ /**
+ * Create a linear block from the received bufferpool data.
+ *
+ * \param data bufferpool data to a linear block
+ *
+ * \return shared pointer to the linear block. nullptr if there was not enough memory to
+ * create this block.
+ */
+ static
+ std::shared_ptr<C2LinearBlock> CreateLinearBlock(
+ const C2Handle *handle,
+ const std::shared_ptr<bufferpool2_BufferPoolData> &data);
+
+ /**
+ * Create a graphic block from the received bufferpool data.
+ *
+ * \param data bufferpool data to a graphic block
+ *
+ * \return shared pointer to the graphic block. nullptr if there was not enough memory to
+ * create this block.
+ */
+ static
+ std::shared_ptr<C2GraphicBlock> CreateGraphicBlock(
+ const C2Handle *handle,
+ const std::shared_ptr<bufferpool2_BufferPoolData> &data);
+
+ /**
+ * Get bufferpool data from the blockpool data.
+ *
+ * \param poolData blockpool data
+ * \param bufferPoolData pointer to bufferpool data where the bufferpool
+ * data is stored.
+ *
+ * \return {\code true} when there is valid bufferpool data, {\code false} otherwise.
+ */
+ static
+ bool GetBufferPoolData(
+ const std::shared_ptr<const _C2BlockPoolData> &poolData,
+ std::shared_ptr<bufferpool2_BufferPoolData> *bufferPoolData);
/*
* Life Cycle Management of BufferQueue-Based Blocks
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 5ea4926..68a8590 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -1091,80 +1091,6 @@
return convertReinterpret<int32_t>(legacy);
}
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl) {
- switch (aidl) {
- case media::AudioDualMonoMode::OFF:
- return AUDIO_DUAL_MONO_MODE_OFF;
- case media::AudioDualMonoMode::LR:
- return AUDIO_DUAL_MONO_MODE_LR;
- case media::AudioDualMonoMode::LL:
- return AUDIO_DUAL_MONO_MODE_LL;
- case media::AudioDualMonoMode::RR:
- return AUDIO_DUAL_MONO_MODE_RR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
- switch (legacy) {
- case AUDIO_DUAL_MONO_MODE_OFF:
- return media::AudioDualMonoMode::OFF;
- case AUDIO_DUAL_MONO_MODE_LR:
- return media::AudioDualMonoMode::LR;
- case AUDIO_DUAL_MONO_MODE_LL:
- return media::AudioDualMonoMode::LL;
- case AUDIO_DUAL_MONO_MODE_RR:
- return media::AudioDualMonoMode::RR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl) {
- return convertReinterpret<audio_timestretch_fallback_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl) {
- return convertReinterpret<audio_timestretch_stretch_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl) {
- audio_playback_rate_t legacy;
- legacy.mSpeed = aidl.speed;
- legacy.mPitch = aidl.pitch;
- legacy.mFallbackMode = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(aidl.fallbackMode));
- legacy.mStretchMode = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(aidl.stretchMode));
- return legacy;
-}
-
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
- media::AudioPlaybackRate aidl;
- aidl.speed = legacy.mSpeed;
- aidl.pitch = legacy.mPitch;
- aidl.fallbackMode = VALUE_OR_RETURN(
- legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(legacy.mFallbackMode));
- aidl.stretchMode = VALUE_OR_RETURN(
- legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(legacy.mStretchMode));
- return aidl;
-}
-
ConversionResult<TrackSecondaryOutputInfoPair>
aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
const media::TrackSecondaryOutputInfo& aidl) {
@@ -1237,25 +1163,4 @@
indexToEnum_bitmask<audio_direct_mode_t>,
enumToMask_index<int32_t, media::AudioDirectMode>);
}
-
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl) {
- switch (aidl) {
- case media::LatencyMode::FREE:
- return AUDIO_LATENCY_MODE_FREE;
- case media::LatencyMode::LOW:
- return AUDIO_LATENCY_MODE_LOW;
- }
- return unexpected(BAD_VALUE);
-}
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy) {
- switch (legacy) {
- case AUDIO_LATENCY_MODE_FREE:
- return media::LatencyMode::FREE;
- case AUDIO_LATENCY_MODE_LOW:
- return media::LatencyMode::LOW;
- }
- return unexpected(BAD_VALUE);
-}
} // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 4679731..9ddae1e 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -281,14 +281,12 @@
"aidl/android/media/AudioAttributesInternal.aidl",
"aidl/android/media/AudioClient.aidl",
"aidl/android/media/AudioDirectMode.aidl",
- "aidl/android/media/AudioDualMonoMode.aidl",
"aidl/android/media/AudioFlag.aidl",
"aidl/android/media/AudioGainSys.aidl",
"aidl/android/media/AudioHalVersion.aidl",
"aidl/android/media/AudioIoConfigEvent.aidl",
"aidl/android/media/AudioIoDescriptor.aidl",
"aidl/android/media/AudioPatchFw.aidl",
- "aidl/android/media/AudioPlaybackRate.aidl",
"aidl/android/media/AudioPortFw.aidl",
"aidl/android/media/AudioPortSys.aidl",
"aidl/android/media/AudioPortConfigFw.aidl",
@@ -303,7 +301,6 @@
"aidl/android/media/AudioUniqueIdUse.aidl",
"aidl/android/media/AudioVibratorInfo.aidl",
"aidl/android/media/EffectDescriptor.aidl",
- "aidl/android/media/LatencyMode.aidl",
"aidl/android/media/TrackSecondaryOutputInfo.aidl",
],
imports: [
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 5a1dc64..ad03711 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -672,12 +672,12 @@
}
Status AudioSystem::AudioFlingerClient::onSupportedLatencyModesChanged(
- int output, const std::vector<media::LatencyMode>& latencyModes) {
+ int output, const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_io_handle_t(output));
std::vector<audio_latency_mode_t> modesLegacy = VALUE_OR_RETURN_BINDER_STATUS(
convertContainer<std::vector<audio_latency_mode_t>>(
- latencyModes, aidl2legacy_LatencyMode_audio_latency_mode_t));
+ latencyModes, aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
std::vector<sp<SupportedLatencyModesCallback>> callbacks;
{
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 22bd2a3..9386b9b 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1266,7 +1266,7 @@
status_t AudioTrack::getDualMonoMode(audio_dual_mono_mode_t* mode) const
{
AutoMutex lock(mLock);
- media::AudioDualMonoMode mediaMode;
+ media::audio::common::AudioDualMonoMode mediaMode;
const status_t status = statusTFromBinderStatus(mAudioTrack->getDualMonoMode(&mediaMode));
if (status == NO_ERROR) {
*mode = VALUE_OR_RETURN_STATUS(
@@ -1381,7 +1381,7 @@
{
AutoMutex lock(mLock);
if (isOffloadedOrDirect_l()) {
- media::AudioPlaybackRate playbackRateTemp;
+ media::audio::common::AudioPlaybackRate playbackRateTemp;
const status_t status = statusTFromBinderStatus(
mAudioTrack->getPlaybackRateParameters(&playbackRateTemp));
if (status == NO_ERROR) { // update local version if changed.
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index d895f80..30ccefe 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -822,8 +822,8 @@
status_t AudioFlingerClientAdapter::setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode) {
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- media::LatencyMode modeAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_latency_mode_t_LatencyMode(mode));
+ media::audio::common::AudioLatencyMode modeAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
return statusTFromBinderStatus(mDelegate->setRequestedLatencyMode(outputAidl, modeAidl));
}
@@ -834,14 +834,14 @@
}
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- std::vector<media::LatencyMode> modesAidl;
+ std::vector<media::audio::common::AudioLatencyMode> modesAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mDelegate->getSupportedLatencyModes(outputAidl, &modesAidl)));
*modes = VALUE_OR_RETURN_STATUS(
convertContainer<std::vector<audio_latency_mode_t>>(modesAidl,
- aidl2legacy_LatencyMode_audio_latency_mode_t));
+ aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
return NO_ERROR;
}
@@ -1377,17 +1377,17 @@
}
Status AudioFlingerServerAdapter::setRequestedLatencyMode(
- int32_t output, media::LatencyMode modeAidl) {
+ int32_t output, media::audio::common::AudioLatencyMode modeAidl) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_io_handle_t(output));
audio_latency_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(
- aidl2legacy_LatencyMode_audio_latency_mode_t(modeAidl));
+ aidl2legacy_AudioLatencyMode_audio_latency_mode_t(modeAidl));
return Status::fromStatusT(mDelegate->setRequestedLatencyMode(
outputLegacy, modeLegacy));
}
Status AudioFlingerServerAdapter::getSupportedLatencyModes(
- int output, std::vector<media::LatencyMode>* _aidl_return) {
+ int output, std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_io_handle_t(output));
std::vector<audio_latency_mode_t> modesLegacy;
@@ -1395,8 +1395,8 @@
RETURN_BINDER_IF_ERROR(mDelegate->getSupportedLatencyModes(outputLegacy, &modesLegacy));
*_aidl_return = VALUE_OR_RETURN_BINDER(
- convertContainer<std::vector<media::LatencyMode>>(
- modesLegacy, legacy2aidl_audio_latency_mode_t_LatencyMode));
+ convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+ modesLegacy, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
return Status::ok();
}
diff --git a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl b/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
deleted file mode 100644
index f6220c2..0000000
--- a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-package android.media;
-
-// TODO(b/175167149): Reconcile AudioDualMonoMode with framework-media-sources
-
-@Backing(type="int")
-enum AudioDualMonoMode {
- OFF = 0,
- LR = 1,
- LL = 2,
- RR = 3,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl b/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
deleted file mode 100644
index e29d398..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-package android.media;
-
-/**
- * The AudioPlaybackRate.
- *
- * See https://developer.android.com/reference/android/media/PlaybackParams.
- * TODO(b/175166815): Reconcile with framework-media-sources PlaybackParams.aidl.
- * As this is used for native wire serialization, no need to define
- * audio_timestretch_stretch_mode_t and audio_timestretch_fallback_mode_t enums
- * until we attempt to unify with PlaybackParams.
- *
- * {@hide}
- */
-parcelable AudioPlaybackRate {
- /** Speed of audio playback, >= 0.f, 1.f nominal (system limits are further restrictive) */
- float speed;
- /** Pitch of audio, >= 0.f, 1.f nominal (system limits are further restrictive) */
- float pitch;
- /** Interpreted as audio_timestretch_stretch_mode_t */
- int stretchMode;
- /** Interpreted as audio_timestretch_fallback_mode_t */
- int fallbackMode;
-}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
index a2bb024..f055cc4 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
@@ -18,7 +18,7 @@
import android.media.AudioIoConfigEvent;
import android.media.AudioIoDescriptor;
-import android.media.LatencyMode;
+import android.media.audio.common.AudioLatencyMode;
/**
* A callback interface for AudioFlinger.
@@ -31,7 +31,8 @@
/**
* Called when the latency modes supported on a given output stream change.
* output is the I/O handle of the output stream for which the change is signalled.
- * latencyModes is the new list of supported latency modes (See LatencyMode.aidl).
+ * latencyModes is the new list of supported latency modes (See AudioLatencyMode.aidl).
*/
- oneway void onSupportedLatencyModesChanged(int output, in LatencyMode[] latencyModes);
+ oneway void onSupportedLatencyModesChanged(
+ int output, in AudioLatencyMode[] latencyModes);
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 7deb384..69810c0 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -37,12 +37,12 @@
import android.media.IAudioTrack;
import android.media.ISoundDose;
import android.media.ISoundDoseCallback;
-import android.media.LatencyMode;
import android.media.MicrophoneInfoData;
import android.media.RenderPosition;
import android.media.TrackSecondaryOutputInfo;
import android.media.audio.common.AudioChannelLayout;
import android.media.audio.common.AudioFormatDescription;
+import android.media.audio.common.AudioLatencyMode;
import android.media.audio.common.AudioMMapPolicyInfo;
import android.media.audio.common.AudioMMapPolicyType;
import android.media.audio.common.AudioMode;
@@ -230,21 +230,21 @@
void setDeviceConnectedState(in AudioPortFw devicePort, boolean connected);
/**
- * Requests a given latency mode (See LatencyMode.aidl) on an output stream.
+ * Requests a given latency mode (See AudioLatencyMode.aidl) on an output stream.
* This can be used when some use case on a given mixer/stream can only be enabled
* if a specific latency mode is selected on the audio path below the HAL.
* For instance spatial audio with head tracking.
* output is the I/O handle of the output stream for which the request is made.
* latencyMode is the requested latency mode.
*/
- void setRequestedLatencyMode(int output, LatencyMode latencyMode);
+ void setRequestedLatencyMode(int output, AudioLatencyMode latencyMode);
/**
* Queries the list of latency modes (See LatencyMode.aidl) supported by an output stream.
* output is the I/O handle of the output stream to which the query applies.
* returns the list of supported latency modes.
*/
- LatencyMode[] getSupportedLatencyModes(int output);
+ AudioLatencyMode[] getSupportedLatencyModes(int output);
/**
* Requests if the implementation supports controlling the latency modes
diff --git a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
index ac58925..c3a2dbe 100644
--- a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
@@ -16,13 +16,13 @@
package android.media;
-import android.media.AudioDualMonoMode;
-import android.media.AudioPlaybackRate;
import android.media.AudioTimestampInternal;
import android.media.SharedFileRegion;
import android.media.VolumeShaperConfiguration;
import android.media.VolumeShaperOperation;
import android.media.VolumeShaperState;
+import android.media.audio.common.AudioDualMonoMode;
+import android.media.audio.common.AudioPlaybackRate;
/**
* Unless otherwise noted, methods returning int expect it to be interpreted as a status_t.
diff --git a/media/libaudioclient/aidl/android/media/LatencyMode.aidl b/media/libaudioclient/aidl/android/media/LatencyMode.aidl
deleted file mode 100644
index 0b2a72b..0000000
--- a/media/libaudioclient/aidl/android/media/LatencyMode.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2021 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.
- */
-
-package android.media;
-
-/**
- * The latency mode currently used by the spatializer mixer.
- * {@hide}
- */
-@Backing(type="byte")
-enum LatencyMode {
- /** No specific constraint on the latency */
- FREE = 0,
- /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */
- LOW = 1,
-}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index ff3598f..a1012a1 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -24,18 +24,15 @@
#include <android/media/AudioAttributesInternal.h>
#include <android/media/AudioClient.h>
#include <android/media/AudioDirectMode.h>
-#include <android/media/AudioDualMonoMode.h>
#include <android/media/AudioFlag.h>
#include <android/media/AudioIoConfigEvent.h>
#include <android/media/AudioIoDescriptor.h>
-#include <android/media/AudioPlaybackRate.h>
#include <android/media/AudioPortFw.h>
#include <android/media/AudioPortConfigFw.h>
#include <android/media/AudioPortDeviceExtSys.h>
#include <android/media/AudioTimestampInternal.h>
#include <android/media/AudioUniqueIdUse.h>
#include <android/media/EffectDescriptor.h>
-#include <android/media/LatencyMode.h>
#include <android/media/TrackSecondaryOutputInfo.h>
#include <android/media/SharedFileRegion.h>
@@ -184,26 +181,6 @@
ConversionResult<int32_t>
legacy2aidl_volume_group_t_int32_t(volume_group_t legacy);
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl);
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy);
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy);
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl);
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
-
using TrackSecondaryOutputInfoPair = std::pair<audio_port_handle_t, std::vector<audio_io_handle_t>>;
ConversionResult<TrackSecondaryOutputInfoPair>
aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
@@ -220,9 +197,4 @@
ConversionResult<audio_direct_mode_t> aidl2legacy_int32_t_audio_direct_mode_t_mask(int32_t aidl);
ConversionResult<int32_t> legacy2aidl_audio_direct_mode_t_int32_t_mask(audio_direct_mode_t legacy);
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl);
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy);
-
} // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 5ed8219..fedf511 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -778,7 +778,8 @@
const media::AudioIoDescriptor& ioDesc) override;
binder::Status onSupportedLatencyModesChanged(
- int output, const std::vector<media::LatencyMode>& latencyModes) override;
+ int output,
+ const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) override;
status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
audio_io_handle_t audioIo,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index fdf3113..6b6c407 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -709,9 +709,10 @@
Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
Status setDeviceConnectedState(const media::AudioPortFw& port, bool connected) override;
- Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
+ Status setRequestedLatencyMode(
+ int output, media::audio::common::AudioLatencyMode mode) override;
Status getSupportedLatencyModes(int output,
- std::vector<media::LatencyMode>* _aidl_return) override;
+ std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) override;
Status setBluetoothVariableLatencyEnabled(bool enabled) override;
Status isBluetoothVariableLatencyEnabled(bool* enabled) override;
Status supportsBluetoothVariableLatency(bool* support) override;
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 9e663bc..75d576e 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -391,7 +391,8 @@
EXPECT_EQ(initial, convBack.value());
}
INSTANTIATE_TEST_SUITE_P(AudioStandard, AudioStandardRoundTripTest,
- testing::Values(AudioStandard::NONE, AudioStandard::EDID));
+ testing::Values(AudioStandard::NONE, AudioStandard::EDID,
+ AudioStandard::SADB, AudioStandard::VSADB));
class AudioEncapsulationMetadataTypeRoundTripTest
: public testing::TestWithParam<AudioEncapsulationMetadataType> {};
@@ -450,7 +451,11 @@
ExtraAudioDescriptor, ExtraAudioDescriptorRoundTripTest,
testing::Values(std::make_tuple(AudioStandard::NONE, AudioEncapsulationType::NONE),
std::make_tuple(AudioStandard::EDID, AudioEncapsulationType::NONE),
- std::make_tuple(AudioStandard::EDID, AudioEncapsulationType::IEC61937)));
+ std::make_tuple(AudioStandard::EDID, AudioEncapsulationType::IEC61937),
+ std::make_tuple(AudioStandard::SADB, AudioEncapsulationType::NONE),
+ std::make_tuple(AudioStandard::SADB, AudioEncapsulationType::IEC61937),
+ std::make_tuple(AudioStandard::VSADB, AudioEncapsulationType::NONE),
+ std::make_tuple(AudioStandard::VSADB, AudioEncapsulationType::IEC61937)));
TEST(AudioPortSessionExtRoundTripTest, Aidl2Legacy2Aidl) {
const int32_t initial = 7;
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 41d4e16..4b6d5f2 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -24,6 +24,7 @@
defaults: [
"latest_android_media_audio_common_types_cpp_shared",
+ "latest_android_hardware_audio_sounddose_ndk_shared",
],
srcs: [
@@ -76,6 +77,7 @@
"libutils",
"liblog",
"libbinder",
+ "libbinder_ndk",
"libaudioclient",
"libaudiomanager",
"libmedialogservice",
@@ -105,11 +107,11 @@
"libaudiohal_headers",
"libaudioutils_headers",
"libmedia_headers",
- "libsounddose_headers",
],
export_shared_lib_headers: [
"libpermission",
+ "android.hardware.audio.sounddose-V1-ndk",
],
cflags: [
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d3453f5..d930fb5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2220,9 +2220,9 @@
void AudioFlinger::onSupportedLatencyModesChanged(
audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
int32_t outputAidl = VALUE_OR_FATAL(legacy2aidl_audio_io_handle_t_int32_t(output));
- std::vector<media::LatencyMode> modesAidl = VALUE_OR_FATAL(
- convertContainer<std::vector<media::LatencyMode>>(modes,
- legacy2aidl_audio_latency_mode_t_LatencyMode));
+ std::vector<media::audio::common::AudioLatencyMode> modesAidl = VALUE_OR_FATAL(
+ convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+ modes, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
Mutex::Autolock _l(mClientLock);
size_t size = mNotificationClients.size();
@@ -2573,6 +2573,9 @@
ALOGE("loadHwModule() error %d loading module %s", rc, name);
return AUDIO_MODULE_HANDLE_NONE;
}
+ if (!mMelReporter->activateHalSoundDoseComputation(name)) {
+ ALOGW("loadHwModule() sound dose reporting is not available");
+ }
mHardwareStatus = AUDIO_HW_INIT;
rc = dev->initCheck();
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 6dd1cda..173f0c9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include <limits.h>
+#include <aidl/android/hardware/audio/sounddose/ISoundDoseFactory.h>
#include <android/media/BnAudioTrack.h>
#include <android/media/IAudioFlingerClient.h>
#include <android/media/IAudioTrackCallback.h>
@@ -701,14 +702,16 @@
binder::Status getVolumeShaperState(
int32_t id,
std::optional<media::VolumeShaperState>* _aidl_return) override;
- binder::Status getDualMonoMode(media::AudioDualMonoMode* _aidl_return) override;
- binder::Status setDualMonoMode(media::AudioDualMonoMode mode) override;
+ binder::Status getDualMonoMode(
+ media::audio::common::AudioDualMonoMode* _aidl_return) override;
+ binder::Status setDualMonoMode(
+ media::audio::common::AudioDualMonoMode mode) override;
binder::Status getAudioDescriptionMixLevel(float* _aidl_return) override;
binder::Status setAudioDescriptionMixLevel(float leveldB) override;
binder::Status getPlaybackRateParameters(
- media::AudioPlaybackRate* _aidl_return) override;
+ media::audio::common::AudioPlaybackRate* _aidl_return) override;
binder::Status setPlaybackRateParameters(
- const media::AudioPlaybackRate& playbackRate) override;
+ const media::audio::common::AudioPlaybackRate& playbackRate) override;
private:
const sp<PlaybackThread::Track> mTrack;
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index b2e8027..b185959 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -22,12 +22,85 @@
#include <android/media/ISoundDoseCallback.h>
#include <audio_utils/power.h>
+#include <android/binder_manager.h>
#include <utils/Log.h>
+using aidl::android::hardware::audio::core::ISoundDose;
+using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
+
namespace android {
+constexpr std::string_view kSoundDoseInterfaceModule = "/default";
+
+bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module) {
+ if (mSoundDoseManager->forceUseFrameworkMel()) {
+ ALOGD("%s: Forcing use of internal MEL computation.", __func__);
+ activateInternalSoundDoseComputation();
+ return false;
+ }
+
+ if (mSoundDoseFactory == nullptr) {
+ ALOGW("%s: sound dose HAL reporting not available", __func__);
+ activateInternalSoundDoseComputation();
+ return false;
+ }
+
+ std::shared_ptr<ISoundDose> soundDoseInterface;
+ auto result = mSoundDoseFactory->getSoundDose(module, &soundDoseInterface);
+ if (!result.isOk()) {
+ ALOGW("%s: HAL cannot provide sound dose interface for module %s",
+ __func__, module.c_str());
+ activateInternalSoundDoseComputation();
+ return false;
+ }
+
+ if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
+ ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
+ activateInternalSoundDoseComputation();
+ return false;
+ }
+
+ std::lock_guard _l(mLock);
+ mUseHalSoundDoseInterface = true;
+ stopInternalMelComputation();
+ return true;
+}
+
+void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
+ {
+ std::lock_guard _l(mLock);
+ if (!mUseHalSoundDoseInterface) {
+ // no need to start internal MEL on active patches
+ return;
+ }
+ mUseHalSoundDoseInterface = false;
+ }
+
+ mSoundDoseManager->setHalSoundDoseInterface(nullptr);
+
+ for (const auto& activePatches : mActiveMelPatches) {
+ for (const auto& deviceId : activePatches.second.deviceHandles) {
+ startMelComputationForNewPatch(activePatches.second.streamHandle, deviceId);
+ }
+ }
+}
+
+void AudioFlinger::MelReporter::onFirstRef() {
+ mAudioFlinger.mPatchCommandThread->addListener(this);
+
+ std::string interface =
+ std::string(ISoundDoseFactory::descriptor) + kSoundDoseInterfaceModule.data();
+ AIBinder* binder = AServiceManager_checkService(interface.c_str());
+ if (binder == nullptr) {
+ ALOGW("%s service %s doesn't exist", __func__, interface.c_str());
+ return;
+ }
+
+ mSoundDoseFactory = ISoundDoseFactory::fromBinder(ndk::SpAIBinder(binder));
+}
+
bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
- if (mSoundDoseManager.computeCsdOnAllDevices()) {
+ if (mSoundDoseManager->forceComputeCsdOnAllDevices()) {
return true;
}
@@ -65,17 +138,17 @@
&& shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
newPatch.deviceHandles.push_back(deviceId);
+ AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
+ patch.mAudioPatch.sinks[i].ext.device.address};
+ mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
- // Start the MEL calculation in the PlaybackThread
- std::lock_guard _lAf(mAudioFlinger.mLock);
- auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
- if (thread != nullptr) {
- thread->startMelComputation(mSoundDoseManager.getOrCreateProcessorForDevice(
- deviceId,
- newPatch.streamHandle,
- thread->mSampleRate,
- thread->mChannelCount,
- thread->mFormat));
+ bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
+ {
+ std::lock_guard _l(mLock);
+ useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
+ }
+ if (!useHalSoundDoseInterface) {
+ startMelComputationForNewPatch(streamHandle, deviceId);
}
}
}
@@ -84,6 +157,21 @@
mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
}
+void AudioFlinger::MelReporter::startMelComputationForNewPatch(
+ audio_io_handle_t streamHandle, audio_port_handle_t deviceId) {
+ // Start the MEL calculation in the PlaybackThread
+ std::lock_guard _lAf(mAudioFlinger.mLock);
+ auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
+ if (thread != nullptr) {
+ thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice(
+ deviceId,
+ streamHandle,
+ thread->mSampleRate,
+ thread->mChannelCount,
+ thread->mFormat));
+ }
+}
+
void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
ALOGV("%s", __func__);
@@ -103,25 +191,47 @@
mActiveMelPatches.erase(patchIt);
}
- // Stop MEL calculation for the PlaybackThread
- std::lock_guard _lAf(mAudioFlinger.mLock);
- mSoundDoseManager.removeStreamProcessor(melPatch.streamHandle);
- auto thread = mAudioFlinger.checkPlaybackThread_l(melPatch.streamHandle);
- if (thread != nullptr) {
- thread->stopMelComputation();
+ for (const auto& deviceId : melPatch.deviceHandles) {
+ mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
}
+ stopInternalMelComputationForStream(melPatch.streamHandle);
}
sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
const sp<media::ISoundDoseCallback>& callback) {
// no need to lock since getSoundDoseInterface is synchronized
- return mSoundDoseManager.getSoundDoseInterface(callback);
+ return mSoundDoseManager->getSoundDoseInterface(callback);
+}
+
+void AudioFlinger::MelReporter::stopInternalMelComputation() {
+ ALOGV("%s", __func__);
+ std::unordered_map<audio_patch_handle_t, ActiveMelPatch> activePatchesCopy;
+ {
+ std::lock_guard _l(mLock);
+ activePatchesCopy = mActiveMelPatches;
+ mActiveMelPatches.clear();
+ }
+
+ for (const auto& activePatch : activePatchesCopy) {
+ stopInternalMelComputationForStream(activePatch.second.streamHandle);
+ }
+}
+
+void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) {
+ ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId);
+
+ std::lock_guard _lAf(mAudioFlinger.mLock);
+ mSoundDoseManager->removeStreamProcessor(streamId);
+ auto thread = mAudioFlinger.checkPlaybackThread_l(streamId);
+ if (thread != nullptr) {
+ thread->stopMelComputation();
+ }
}
std::string AudioFlinger::MelReporter::dump() {
std::lock_guard _l(mLock);
std::string output("\nSound Dose:\n");
- output.append(mSoundDoseManager.dump());
+ output.append(mSoundDoseManager->dump());
return output;
}
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index b1abc59..acbc8ed 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -32,17 +32,34 @@
class MelReporter : public PatchCommandThread::PatchCommandListener {
public:
explicit MelReporter(AudioFlinger& audioFlinger)
- : mAudioFlinger(audioFlinger) {}
+ : mAudioFlinger(audioFlinger),
+ mSoundDoseManager(sp<SoundDoseManager>::make()) {}
- void onFirstRef() override {
- mAudioFlinger.mPatchCommandThread->addListener(this);
- }
+ void onFirstRef() override;
/** Returns true if we should compute MEL for the given device. */
bool shouldComputeMelForDeviceType(audio_devices_t device);
- // For now only support internal MelReporting
- [[nodiscard]] bool isHalReportingEnabled() const { return false; }
+ /**
+ * Activates the MEL reporting from the HAL sound dose interface. If the HAL
+ * does not support the sound dose interface for this module, the internal MEL
+ * calculation will be use.
+ *
+ * For now support internal MelReporting only if the sound dose standalone HAL
+ * is not implemented
+ *
+ * @return true if the MEL reporting will be done from the sound dose HAL
+ * interface
+ */
+ bool activateHalSoundDoseComputation(const std::string& module);
+
+ /**
+ * Activates the MEL reporting from internal framework values. These are used
+ * as a fallback when there is no sound dose interface implementation from HAL.
+ * Note: the internal CSD computation does not guarantee a certification with
+ * IEC62368-1 3rd edition or EN50332-3
+ */
+ void activateInternalSoundDoseComputation();
sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
@@ -54,9 +71,17 @@
void onReleaseAudioPatch(audio_patch_handle_t handle) override;
private:
- AudioFlinger& mAudioFlinger; // does not own the object
+ void stopInternalMelComputation();
+ void stopInternalMelComputationForStream(audio_io_handle_t streamId);
- SoundDoseManager mSoundDoseManager;
+ void startMelComputationForNewPatch(audio_io_handle_t streamHandle,
+ audio_port_handle_t deviceId);
+
+ AudioFlinger& mAudioFlinger; // does not own the object
+ std::shared_ptr<::aidl::android::hardware::audio::sounddose::ISoundDoseFactory>
+ mSoundDoseFactory;
+
+ sp<SoundDoseManager> mSoundDoseManager;
struct ActiveMelPatch {
audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE};
@@ -70,4 +95,5 @@
std::mutex mLock;
std::unordered_map<audio_patch_handle_t, ActiveMelPatch>
mActiveMelPatches GUARDED_BY(AudioFlinger::MelReporter::mLock);
+ bool mUseHalSoundDoseInterface GUARDED_BY(AudioFlinger::MelReporter::mLock) = false;
};
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9598ed9..3dcf932 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -273,8 +273,8 @@
static std::string toString(audio_latency_mode_t mode) {
// We convert to the AIDL type to print (eventually the legacy type will be removed).
- const auto result = legacy2aidl_audio_latency_mode_t_LatencyMode(mode);
- return result.has_value() ? media::toString(*result) : "UNKNOWN";
+ const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+ return result.has_value() ? media::audio::common::toString(*result) : "UNKNOWN";
}
// Could be made a template, but other toString overloads for std::vector are confused.
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index ac863b5..382e4f9 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -440,7 +440,8 @@
return Status::ok();
}
-Status AudioFlinger::TrackHandle::getDualMonoMode(media::AudioDualMonoMode* _aidl_return)
+Status AudioFlinger::TrackHandle::getDualMonoMode(
+ media::audio::common::AudioDualMonoMode* _aidl_return)
{
audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
const status_t status = mTrack->getDualMonoMode(&mode)
@@ -453,7 +454,7 @@
}
Status AudioFlinger::TrackHandle::setDualMonoMode(
- media::AudioDualMonoMode mode)
+ media::audio::common::AudioDualMonoMode mode)
{
const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
@@ -477,7 +478,7 @@
}
Status AudioFlinger::TrackHandle::getPlaybackRateParameters(
- media::AudioPlaybackRate* _aidl_return)
+ media::audio::common::AudioPlaybackRate* _aidl_return)
{
audio_playback_rate_t localPlaybackRate{};
status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
@@ -490,7 +491,7 @@
}
Status AudioFlinger::TrackHandle::setPlaybackRateParameters(
- const media::AudioPlaybackRate& playbackRate)
+ const media::audio::common::AudioPlaybackRate& playbackRate)
{
const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
@@ -792,7 +793,7 @@
" Format Chn mask SRate "
"ST Usg CT "
" G db L dB R dB VS dB "
- " Server FrmCnt FrmRdy F Underruns Flushed"
+ " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
"%s\n",
isServerLatencySupported() ? " Latency" : "");
}
@@ -878,7 +879,7 @@
"%08X %08X %6u "
"%2u %3x %2x "
"%5.2g %5.2g %5.2g %5.2g%c "
- "%08X %6zu%c %6zu %c %9u%c %7u",
+ "%08X %6zu%c %6zu %c %9u%c %7u %10s",
active ? "yes" : "no",
(mClient == 0) ? getpid() : mClient->pid(),
mSessionId,
@@ -907,7 +908,8 @@
fillingStatus,
mAudioTrackServerProxy->getUnderrunFrames(),
nowInUnderrun,
- (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000
+ (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
+ isBitPerfect() ? "true" : "false"
);
if (isServerLatencySupported()) {
@@ -1160,6 +1162,23 @@
}
if (status == NO_ERROR) {
forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
+
+ // send format to AudioManager for playback activity monitoring
+ sp<IAudioManager> audioManager = thread->mAudioFlinger->getOrCreateAudioManager();
+ if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
+ std::unique_ptr<os::PersistableBundle> bundle =
+ std::make_unique<os::PersistableBundle>();
+ bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
+ isSpatialized());
+ bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
+ bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
+ status_t result = audioManager->portEvent(mPortId,
+ PLAYER_UPDATE_FORMAT, bundle);
+ if (result != OK) {
+ ALOGE("%s: unable to send playback format for port ID %d, status error %d",
+ __func__, mPortId, result);
+ }
+ }
}
return status;
}
diff --git a/services/audioflinger/sounddose/Android.bp b/services/audioflinger/sounddose/Android.bp
index 0e409d3..6d9a0cc 100644
--- a/services/audioflinger/sounddose/Android.bp
+++ b/services/audioflinger/sounddose/Android.bp
@@ -12,15 +12,24 @@
double_loadable: true,
+ defaults: [
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_core_sounddose_ndk_shared",
+ "latest_android_hardware_audio_sounddose_ndk_shared",
+ ],
+
srcs: [
"SoundDoseManager.cpp",
],
shared_libs: [
"audioflinger-aidl-cpp",
+ "libaudio_aidl_conversion_common_ndk",
+ "libaudiofoundation",
"libaudioutils",
"libbase",
"libbinder",
+ "libbinder_ndk",
"liblog",
"libutils",
],
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index 61f27cb..df6eb5b 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -20,14 +20,22 @@
#include "SoundDoseManager.h"
+#if !defined(BACKEND_NDK)
+#define BACKEND_NDK
+#endif
+
+#include "android/media/SoundDoseRecord.h"
#include <android-base/stringprintf.h>
+#include <media/AidlConversionCppNdk.h>
+#include <cinttypes>
#include <time.h>
#include <utils/Log.h>
-#include <cinttypes>
-#include "android/media/SoundDoseRecord.h"
namespace android {
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+
namespace {
int64_t getMonotonicSecond() {
@@ -46,6 +54,11 @@
size_t channelCount, audio_format_t format) {
std::lock_guard _l(mLock);
+ if (mHalSoundDose != nullptr) {
+ ALOGW("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
+ return nullptr;
+ }
+
auto streamProcessor = mActiveProcessors.find(streamHandle);
sp<audio_utils::MelProcessor> processor;
if (streamProcessor != mActiveProcessors.end() &&
@@ -63,11 +76,54 @@
}
}
+bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose) {
+ ALOGV("%s", __func__);
+
+ {
+ std::lock_guard _l(mLock);
+
+ mHalSoundDose = halSoundDose;
+ if (halSoundDose == nullptr) {
+ ALOGI("%s: passed ISoundDose object is null, switching to internal CSD", __func__);
+ return false;
+ }
+
+ if (!mHalSoundDose->setOutputRs2(mRs2Value).isOk()) {
+ ALOGW("%s: Cannot set RS2 value for momentary exposure %f",
+ __func__,
+ mRs2Value);
+ }
+
+ // initialize the HAL sound dose callback lazily
+ if (mHalSoundDoseCallback == nullptr) {
+ mHalSoundDoseCallback =
+ ndk::SharedRefBase::make<HalSoundDoseCallback>(this);
+ }
+ }
+
+ auto status = halSoundDose->registerSoundDoseCallback(mHalSoundDoseCallback);
+ if (!status.isOk()) {
+ // Not a warning since this can happen if the callback was registered before
+ ALOGI("%s: Cannot register HAL sound dose callback with status message: %s",
+ __func__,
+ status.getMessage());
+ }
+
+ return true;
+}
+
void SoundDoseManager::setOutputRs2(float rs2Value) {
ALOGV("%s", __func__);
std::lock_guard _l(mLock);
mRs2Value = rs2Value;
+ if (mHalSoundDose != nullptr) {
+ // using the HAL sound dose interface
+ if (!mHalSoundDose->setOutputRs2(mRs2Value).isOk()) {
+ ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, mRs2Value);
+ }
+ return;
+ }
for (auto& streamProcessor : mActiveProcessors) {
sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
@@ -89,6 +145,103 @@
}
}
+audio_port_handle_t SoundDoseManager::getIdForAudioDevice(const AudioDevice& audioDevice) const {
+ std::lock_guard _l(mLock);
+
+ audio_devices_t type;
+ std::string address;
+ auto result = aidl::android::aidl2legacy_AudioDevice_audio_device(
+ audioDevice, &type, &address);
+ if (result != NO_ERROR) {
+ ALOGE("%s: could not convert from AudioDevice to AudioDeviceTypeAddr", __func__);
+ return AUDIO_PORT_HANDLE_NONE;
+ }
+
+ auto adt = AudioDeviceTypeAddr(type, address);
+ auto deviceIt = mActiveDevices.find(adt);
+ if (deviceIt == mActiveDevices.end()) {
+ ALOGE("%s: could not find port id for device %s", __func__, adt.toString().c_str());
+ return AUDIO_PORT_HANDLE_NONE;
+ }
+ return deviceIt->second;
+}
+
+void SoundDoseManager::mapAddressToDeviceId(const AudioDeviceTypeAddr& adt,
+ const audio_port_handle_t deviceId) {
+ std::lock_guard _l(mLock);
+ ALOGI("%s: map address: %s to device id: %d", __func__, adt.toString().c_str(), deviceId);
+ mActiveDevices[adt] = deviceId;
+}
+
+void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) {
+ std::lock_guard _l(mLock);
+ for (auto activeDevice = mActiveDevices.begin(); activeDevice != mActiveDevices.end();) {
+ if (activeDevice->second == deviceId) {
+ ALOGI("%s: clear mapping addr: %s to deviceId: %d",
+ __func__, activeDevice->first.toString().c_str(), deviceId);
+ activeDevice = mActiveDevices.erase(activeDevice);
+ continue;
+ }
+ ++activeDevice;
+ }
+ return;
+}
+
+ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning(
+ float in_currentDbA, const AudioDevice& in_audioDevice) {
+ auto soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+
+ std::shared_ptr<ISoundDose> halSoundDose;
+ soundDoseManager->getHalSoundDose(&halSoundDose);
+ if(halSoundDose == nullptr) {
+ ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+
+ auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
+ if (id == AUDIO_PORT_HANDLE_NONE) {
+ ALOGW("%s: no mapped id for audio device with type %d and address %s",
+ __func__, in_audioDevice.type.type,
+ in_audioDevice.address.get<AudioDeviceAddress::id>().c_str());
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ soundDoseManager->onMomentaryExposure(in_currentDbA, id);
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onNewMelValues(
+ const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
+ const AudioDevice& in_audioDevice) {
+ auto soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+
+ std::shared_ptr<ISoundDose> halSoundDose;
+ soundDoseManager->getHalSoundDose(&halSoundDose);
+ if(halSoundDose == nullptr) {
+ ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+
+ auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
+ if (id == AUDIO_PORT_HANDLE_NONE) {
+ ALOGW("%s: no mapped id for audio device with type %d and address %s",
+ __func__, in_audioDevice.type.type,
+ in_audioDevice.address.get<AudioDeviceAddress::id>().c_str());
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ // TODO: introduce timestamp in onNewMelValues callback
+ soundDoseManager->onNewMelValues(in_melRecord.melValues, 0,
+ in_melRecord.melValues.size(), id);
+
+ return ndk::ScopedAStatus::ok();
+}
+
void SoundDoseManager::SoundDose::binderDied(__unused const wp<IBinder>& who) {
ALOGV("%s", __func__);
@@ -156,11 +309,14 @@
}
void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
+ // invalidate any HAL sound dose interface used
+ setHalSoundDoseInterface(nullptr);
+
std::lock_guard _l(mLock);
mUseFrameworkMel = useFrameworkMel;
}
-bool SoundDoseManager::useFrameworkMel() const {
+bool SoundDoseManager::forceUseFrameworkMel() const {
std::lock_guard _l(mLock);
return mUseFrameworkMel;
}
@@ -170,11 +326,16 @@
mComputeCsdOnAllDevices = computeCsdOnAllDevices;
}
-bool SoundDoseManager::computeCsdOnAllDevices() const {
+bool SoundDoseManager::forceComputeCsdOnAllDevices() const {
std::lock_guard _l(mLock);
return mComputeCsdOnAllDevices;
}
+void SoundDoseManager::getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const {
+ std::lock_guard _l(mLock);
+ *halSoundDose = mHalSoundDose;
+}
+
void SoundDoseManager::resetSoundDose() {
std::lock_guard lock(mLock);
mSoundDose = nullptr;
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index eb5fa49..b10874f 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -17,8 +17,11 @@
#pragma once
+#include <aidl/android/hardware/audio/core/ISoundDose.h>
+#include <aidl/android/media/audio/common/AudioDevice.h>
#include <android/media/BnSoundDose.h>
#include <android/media/ISoundDoseCallback.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <audio_utils/MelAggregator.h>
#include <audio_utils/MelProcessor.h>
#include <binder/Status.h>
@@ -27,8 +30,10 @@
namespace android {
+using aidl::android::hardware::audio::core::ISoundDose;
+
class SoundDoseManager : public audio_utils::MelProcessor::MelCallback {
- public:
+public:
/** CSD is computed with a rolling window of 7 days. */
static constexpr int64_t kCsdWindowSeconds = 604800; // 60s * 60m * 24h * 7d
/** Default RS2 value in dBA as defined in IEC 62368-1 3rd edition. */
@@ -36,13 +41,13 @@
SoundDoseManager()
: mMelAggregator(sp<audio_utils::MelAggregator>::make(kCsdWindowSeconds)),
- mRs2Value(kDefaultRs2Value){};
+ mRs2Value(kDefaultRs2Value) {};
/**
* \brief Creates or gets the MelProcessor assigned to the streamHandle
*
* \param deviceId id for the devices where the stream is active.
- * \param streanHandle handle to the stream
+ * \param streamHandle handle to the stream
* \param sampleRate sample rate for the processor
* \param channelCount number of channels to be processed.
* \param format format of the input samples.
@@ -58,7 +63,7 @@
/**
* \brief Removes stream processor when MEL computation is not needed anymore
*
- * \param streanHandle handle to the stream
+ * \param streamHandle handle to the stream
*/
void removeStreamProcessor(audio_io_handle_t streamHandle);
@@ -78,13 +83,31 @@
**/
sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
+ /**
+ * Sets the HAL sound dose interface to use for the MEL computation. Use nullptr
+ * for using the internal MEL computation.
+ *
+ * @return true if setting the HAL sound dose value was successful, false otherwise.
+ */
+ bool setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose);
+
+ /** Returns the cached audio port id from the active devices. */
+ audio_port_handle_t getIdForAudioDevice(
+ const aidl::android::media::audio::common::AudioDevice& audioDevice) const;
+
+ /** Caches mapping between address and device port id. */
+ void mapAddressToDeviceId(const AudioDeviceTypeAddr& adt,
+ const audio_port_handle_t deviceId);
+
+ /** Clear all map entries with passed audio_port_handle_t. */
+ void clearMapDeviceIdEntries(audio_port_handle_t deviceId);
+
std::string dump() const;
- // used for testing
+ // used for testing only
size_t getCachedMelRecordsSize() const;
- bool useFrameworkMel() const;
- bool computeCsdOnAllDevices() const;
-
+ bool forceUseFrameworkMel() const;
+ bool forceComputeCsdOnAllDevices() const;
/** Method for converting from audio_utils::CsdRecord to media::SoundDoseRecord. */
static media::SoundDoseRecord csdRecordToSoundDoseRecord(const audio_utils::CsdRecord& legacy);
@@ -101,7 +124,7 @@
public:
SoundDose(SoundDoseManager* manager, const sp<media::ISoundDoseCallback>& callback)
: mSoundDoseManager(manager),
- mSoundDoseCallback(callback) {};
+ mSoundDoseCallback(callback) {}
/** IBinder::DeathRecipient. Listen to the death of ISoundDoseCallback. */
virtual void binderDied(const wp<IBinder>& who);
@@ -119,6 +142,21 @@
const sp<media::ISoundDoseCallback> mSoundDoseCallback;
};
+ class HalSoundDoseCallback : public ISoundDose::BnHalSoundDoseCallback {
+ public:
+ explicit HalSoundDoseCallback(SoundDoseManager* manager)
+ : mSoundDoseManager(manager) {}
+
+ ndk::ScopedAStatus onMomentaryExposureWarning(
+ float in_currentDbA,
+ const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override;
+ ndk::ScopedAStatus onNewMelValues(
+ const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
+ const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override;
+
+ wp<SoundDoseManager> mSoundDoseManager;
+ };
+
void resetSoundDose();
void resetCsd(float currentCsd, const std::vector<media::SoundDoseRecord>& records);
@@ -127,6 +165,8 @@
void setUseFrameworkMel(bool useFrameworkMel);
void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices);
+ /** Returns the HAL sound dose interface or null if internal MEL computation is used. */
+ void getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const;
mutable std::mutex mLock;
@@ -136,12 +176,18 @@
std::unordered_map<audio_io_handle_t, wp<audio_utils::MelProcessor>> mActiveProcessors
GUARDED_BY(mLock);
+ // map active device address and type to device id
+ std::map<AudioDeviceTypeAddr, audio_port_handle_t> mActiveDevices GUARDED_BY(mLock);
+
float mRs2Value GUARDED_BY(mLock);
sp<SoundDose> mSoundDose GUARDED_BY(mLock);
- bool mUseFrameworkMel GUARDED_BY(mLock);
- bool mComputeCsdOnAllDevices GUARDED_BY(mLock);
+ std::shared_ptr<ISoundDose> mHalSoundDose GUARDED_BY(mLock);
+ std::shared_ptr<HalSoundDoseCallback> mHalSoundDoseCallback GUARDED_BY(mLock);
+
+ bool mUseFrameworkMel GUARDED_BY(mLock) = false;
+ bool mComputeCsdOnAllDevices GUARDED_BY(mLock) = false;
};
} // namespace android
diff --git a/services/audioflinger/sounddose/tests/Android.bp b/services/audioflinger/sounddose/tests/Android.bp
index a886663..fef73dc 100644
--- a/services/audioflinger/sounddose/tests/Android.bp
+++ b/services/audioflinger/sounddose/tests/Android.bp
@@ -14,15 +14,24 @@
"sounddosemanager_tests.cpp"
],
+ defaults: [
+ "latest_android_media_audio_common_types_ndk_static",
+ "latest_android_hardware_audio_core_sounddose_ndk_static",
+ "latest_android_hardware_audio_sounddose_ndk_static",
+ ],
+
shared_libs: [
"audioflinger-aidl-cpp",
+ "libaudiofoundation",
"libaudioutils",
"libbase",
+ "libbinder_ndk",
"liblog",
"libutils",
],
static_libs: [
+ "libaudio_aidl_conversion_common_ndk",
"libgmock",
"libsounddose",
],
@@ -37,4 +46,8 @@
"-Werror",
"-Wextra",
],
+
+ test_suites: [
+ "general-tests",
+ ],
}
\ No newline at end of file
diff --git a/services/audioflinger/sounddose/tests/TEST_MAPPING b/services/audioflinger/sounddose/tests/TEST_MAPPING
new file mode 100644
index 0000000..dd7fe4d
--- /dev/null
+++ b/services/audioflinger/sounddose/tests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "sounddosemanager_tests"
+ }
+ ]
+}
diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
index 0aa5a20..ba2edcf 100644
--- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
+++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
@@ -15,25 +15,55 @@
*/
// #define LOG_NDEBUG 0
-#define LOG_TAG "sounddosemanager_tests"
+#define LOG_TAG "SoundDoseManager_tests"
+
+#include <aidl/android/hardware/audio/core/BnSoundDose.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
#include <SoundDoseManager.h>
-#include <gtest/gtest.h>
-
namespace android {
namespace {
-TEST(SoundDoseManagerTest, GetProcessorForExistingStream) {
- SoundDoseManager soundDoseManager;
+using aidl::android::hardware::audio::core::BnSoundDose;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+
+class HalSoundDoseMock : public BnSoundDose {
+public:
+ MOCK_METHOD(ndk::ScopedAStatus, getOutputRs2, (float*), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, setOutputRs2, (float), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, registerSoundDoseCallback,
+ (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>&), (override));
+};
+
+class SoundDoseManagerTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mSoundDoseManager = sp<SoundDoseManager>::make();
+ mHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
+
+ ON_CALL(*mHalSoundDose.get(), setOutputRs2)
+ .WillByDefault([] (float rs2) {
+ EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
+ return ndk::ScopedAStatus::ok();
+ });
+ }
+
+ sp<SoundDoseManager> mSoundDoseManager;
+ std::shared_ptr<HalSoundDoseMock> mHalSoundDose;
+};
+
+TEST_F(SoundDoseManagerTest, GetProcessorForExistingStream) {
sp<audio_utils::MelProcessor> processor1 =
- soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/1,
+ mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/1,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
/*format*/AUDIO_FORMAT_PCM_FLOAT);
sp<audio_utils::MelProcessor> processor2 =
- soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/2,
+ mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
@@ -42,18 +72,17 @@
EXPECT_EQ(processor1, processor2);
}
-TEST(SoundDoseManagerTest, RemoveExistingStream) {
- SoundDoseManager soundDoseManager;
+TEST_F(SoundDoseManagerTest, RemoveExistingStream) {
sp<audio_utils::MelProcessor> processor1 =
- soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/1,
+ mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/1,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
/*format*/AUDIO_FORMAT_PCM_FLOAT);
- soundDoseManager.removeStreamProcessor(1);
+ mSoundDoseManager->removeStreamProcessor(1);
sp<audio_utils::MelProcessor> processor2 =
- soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/2,
+ mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
@@ -62,13 +91,150 @@
EXPECT_NE(processor1, processor2);
}
-TEST(SoundDoseManagerTest, NewMelValuesCacheNewRecord) {
- SoundDoseManager soundDoseManager;
+TEST_F(SoundDoseManagerTest, NewMelValuesCacheNewRecord) {
std::vector<float>mels{1, 1};
- soundDoseManager.onNewMelValues(mels, 0, mels.size(), /*deviceId=*/1);
+ mSoundDoseManager->onNewMelValues(mels, 0, mels.size(), /*deviceId=*/1);
- EXPECT_EQ(soundDoseManager.getCachedMelRecordsSize(), size_t{1});
+ EXPECT_EQ(mSoundDoseManager->getCachedMelRecordsSize(), size_t{1});
+}
+
+TEST_F(SoundDoseManagerTest, InvalidHalInterfaceIsNotSet) {
+ EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+}
+
+TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) {
+ EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+ EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ EXPECT_NE(nullptr, callback);
+ return ndk::ScopedAStatus::ok();
+ });
+
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+
+ EXPECT_EQ(nullptr, mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
+ /*streamHandle=*/1,
+ /*sampleRate*/44100,
+ /*channelCount*/2,
+ /*format*/AUDIO_FORMAT_PCM_FLOAT));
+}
+
+TEST_F(SoundDoseManagerTest, SetHalSoundDoseRegistersHalCallbacks) {
+ EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+ EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ EXPECT_NE(nullptr, callback);
+ return ndk::ScopedAStatus::ok();
+ });
+
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+}
+
+TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgument) {
+ std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
+
+ EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+ EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ halCallback = callback;
+ return ndk::ScopedAStatus::ok();
+ });
+
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+
+ EXPECT_NE(nullptr, halCallback);
+ AudioDevice audioDevice = {};
+ audioDevice.address.set<AudioDeviceAddress::id>("test");
+ auto status = halCallback->onMomentaryExposureWarning(
+ /*in_currentDbA=*/101.f, audioDevice);
+ EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalAfterInternalSelectedReturnsException) {
+ std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
+
+ EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+ EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ halCallback = callback;
+ return ndk::ScopedAStatus::ok();
+ });
+
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_NE(nullptr, halCallback);
+ EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+
+ AudioDevice audioDevice = {};
+ audioDevice.address.set<AudioDeviceAddress::id>("test");
+ auto status = halCallback->onMomentaryExposureWarning(
+ /*in_currentDbA=*/101.f, audioDevice);
+ EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(SoundDoseManagerTest, OnNewMelValuesFromHalWithNoAddressIllegalArgument) {
+ std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
+
+ EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+ EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ halCallback = callback;
+ return ndk::ScopedAStatus::ok();
+ });
+
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+
+ EXPECT_NE(nullptr, halCallback);
+ AudioDevice audioDevice = {};
+ audioDevice.address.set<AudioDeviceAddress::id>("test");
+ auto status = halCallback->onNewMelValues(/*in_melRecord=*/{}, audioDevice);
+ EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(SoundDoseManagerTest, GetIdReturnsMappedAddress) {
+ const std::string address = "testAddress";
+ const audio_port_handle_t deviceId = 2;
+ const AudioDeviceTypeAddr adt{audio_devices_t{0}, address};
+ AudioDevice audioDevice;
+ audioDevice.address.set<AudioDeviceAddress::id>(address);
+
+ mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
+
+ EXPECT_EQ(deviceId, mSoundDoseManager->getIdForAudioDevice(audioDevice));
+}
+
+TEST_F(SoundDoseManagerTest, GetAfterClearIdReturnsNone) {
+ const std::string address = "testAddress";
+ const AudioDeviceTypeAddr adt {audio_devices_t{0}, address};
+ const audio_port_handle_t deviceId = 2;
+ AudioDevice audioDevice;
+ audioDevice.address.set<AudioDeviceAddress::id>(address);
+
+ mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
+ mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
+
+ EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, mSoundDoseManager->getIdForAudioDevice(audioDevice));
+}
+
+TEST_F(SoundDoseManagerTest, GetUnmappedIdReturnsHandleNone) {
+ const std::string address = "testAddress";
+ AudioDevice audioDevice;
+ audioDevice.address.set<AudioDeviceAddress::id>(address);
+
+ EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, mSoundDoseManager->getIdForAudioDevice(audioDevice));
+}
+
+TEST_F(SoundDoseManagerTest, GetDefaultForceComputeCsdOnAllDevices) {
+ EXPECT_FALSE(mSoundDoseManager->forceComputeCsdOnAllDevices());
+}
+
+TEST_F(SoundDoseManagerTest, GetDefaultForceUseFrameworkMel) {
+ EXPECT_FALSE(mSoundDoseManager->forceUseFrameworkMel());
}
} // namespace
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 1d4eb1e..f99f76e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1280,17 +1280,26 @@
info = getPreferredMixerAttributesInfo(
outputDevices.itemAt(0)->getId(),
mEngine->getProductStrategyForAttributes(*resultAttr));
- if (info != nullptr && info->getUid() != uid && info->getActiveClientCount() == 0) {
- // Only use preferred mixer when the requested uid matched or
- // there is active client on preferred mixer.
+ // Only use preferred mixer if the uid matches or the preferred mixer is bit-perfect
+ // and it is currently active.
+ if (info != nullptr && info->getUid() != uid &&
+ ((info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) == AUDIO_OUTPUT_FLAG_NONE ||
+ info->getActiveClientCount() == 0)) {
info = nullptr;
}
}
*output = getOutputForDevices(outputDevices, session, resultAttr, config,
flags, isSpatialized, info, resultAttr->flags & AUDIO_FLAG_MUTE_HAPTIC);
+ // The client will be active if the client is currently preferred mixer owner and the
+ // requested configuration matches the preferred mixer configuration.
*isBitPerfect = (info != nullptr
&& (info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE
- && *output != AUDIO_IO_HANDLE_NONE);
+ && info->getUid() == uid
+ && *output != AUDIO_IO_HANDLE_NONE
+ // When bit-perfect output is selected for the preferred mixer attributes owner,
+ // only need to consider the config matches.
+ && mOutputs.valueFor(*output)->isConfigurationMatched(
+ clientConfig, AUDIO_OUTPUT_FLAG_NONE));
}
if (*output == AUDIO_IO_HANDLE_NONE) {
AudioProfileVector profiles;
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index 3e4dd69..ccbbf66 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -23,6 +23,7 @@
#include <android/media/SpatializationLevel.h>
#include <android/media/SpatializationMode.h>
#include <android/media/SpatializerHeadTrackingMode.h>
+#include <android/media/audio/common/AudioLatencyMode.h>
#include <audio_utils/SimpleLog.h>
#include <math.h>
#include <media/AudioEffect.h>
@@ -167,8 +168,9 @@
static std::string toString(audio_latency_mode_t mode) {
// We convert to the AIDL type to print (eventually the legacy type will be removed).
- const auto result = legacy2aidl_audio_latency_mode_t_LatencyMode(mode);
- return result.has_value() ? media::toString(*result) : "unknown_latency_mode";
+ const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+ return result.has_value() ?
+ media::audio::common::toString(*result) : "unknown_latency_mode";
}
/**
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 7f5c7a5..3f38d01 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -161,7 +161,8 @@
audio_port_handle_t *portId = nullptr,
audio_attributes_t attr = {},
audio_session_t session = AUDIO_SESSION_NONE,
- int uid = 0);
+ int uid = 0,
+ bool* isBitPerfect = nullptr);
void getInputForAttr(
const audio_attributes_t &attr,
audio_session_t session,
@@ -246,7 +247,8 @@
audio_port_handle_t *portId,
audio_attributes_t attr,
audio_session_t session,
- int uid) {
+ int uid,
+ bool* isBitPerfect) {
audio_io_handle_t localOutput;
if (!output) output = &localOutput;
*output = AUDIO_IO_HANDLE_NONE;
@@ -260,14 +262,15 @@
*portId = AUDIO_PORT_HANDLE_NONE;
AudioPolicyInterface::output_type_t outputType;
bool isSpatialized;
- bool isBitPerfect;
+ bool isBitPerfectInternal;
// TODO b/182392769: use attribution source util
AttributionSourceState attributionSource = AttributionSourceState();
attributionSource.uid = uid;
attributionSource.token = sp<BBinder>::make();
ASSERT_EQ(OK, mManager->getOutputForAttr(
&attr, output, session, &stream, attributionSource, &config, &flags,
- selectedDeviceId, portId, {}, &outputType, &isSpatialized, &isBitPerfect));
+ selectedDeviceId, portId, {}, &outputType, &isSpatialized,
+ isBitPerfect == nullptr ? &isBitPerfectInternal : isBitPerfect));
ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
ASSERT_NE(AUDIO_IO_HANDLE_NONE, *output);
}
@@ -1119,6 +1122,116 @@
"", "", AUDIO_FORMAT_LDAC));
}
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, BitPerfectPlayback) {
+ const audio_format_t bitPerfectFormat = AUDIO_FORMAT_PCM_16_BIT;
+ const audio_channel_mask_t bitPerfectChannelMask = AUDIO_CHANNEL_OUT_QUAD;
+ const uint32_t bitPerfectSampleRate = 48000;
+ mClient->addSupportedFormat(bitPerfectFormat);
+ mClient->addSupportedChannelMask(bitPerfectChannelMask);
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_OUT_USB_DEVICE,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ "", "", AUDIO_FORMAT_DEFAULT));
+ auto devices = mManager->getAvailableOutputDevices();
+ audio_port_handle_t usbPortId = AUDIO_PORT_HANDLE_NONE;
+ for (auto device : devices) {
+ if (device->type() == AUDIO_DEVICE_OUT_USB_DEVICE) {
+ usbPortId = device->getId();
+ break;
+ }
+ }
+ EXPECT_NE(AUDIO_PORT_HANDLE_NONE, usbPortId);
+
+ const uid_t uid = 1234;
+ const uid_t anotherUid = 5678;
+ const audio_attributes_t mediaAttr = {
+ .content_type = AUDIO_CONTENT_TYPE_MUSIC,
+ .usage = AUDIO_USAGE_MEDIA,
+ };
+
+ std::vector<audio_mixer_attributes_t> mixerAttributes;
+ EXPECT_EQ(NO_ERROR, mManager->getSupportedMixerAttributes(usbPortId, mixerAttributes));
+ EXPECT_GT(mixerAttributes.size(), 0);
+ size_t bitPerfectIndex = 0;
+ for (; bitPerfectIndex < mixerAttributes.size(); ++bitPerfectIndex) {
+ if (mixerAttributes[bitPerfectIndex].mixer_behavior == AUDIO_MIXER_BEHAVIOR_BIT_PERFECT) {
+ break;
+ }
+ }
+ EXPECT_LT(bitPerfectIndex, mixerAttributes.size());
+ EXPECT_EQ(bitPerfectFormat, mixerAttributes[bitPerfectIndex].config.format);
+ EXPECT_EQ(bitPerfectChannelMask, mixerAttributes[bitPerfectIndex].config.channel_mask);
+ EXPECT_EQ(bitPerfectSampleRate, mixerAttributes[bitPerfectIndex].config.sample_rate);
+ EXPECT_EQ(NO_ERROR,
+ mManager->setPreferredMixerAttributes(
+ &mediaAttr, usbPortId, uid, &mixerAttributes[bitPerfectIndex]));
+
+ audio_io_handle_t bitPerfectOutput = AUDIO_IO_HANDLE_NONE;
+ audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t bitPerfectPortId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
+ bool isBitPerfect;
+
+ // When there is no active bit-perfect playback, the output selection will follow default
+ // routing strategy.
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr, AUDIO_SESSION_NONE,
+ uid, &isBitPerfect);
+ EXPECT_FALSE(isBitPerfect);
+ EXPECT_NE(AUDIO_IO_HANDLE_NONE, output);
+ const auto outputDesc = mManager->getOutputs().valueFor(output);
+ EXPECT_NE(nullptr, outputDesc);
+ EXPECT_NE(AUDIO_OUTPUT_FLAG_BIT_PERFECT, outputDesc->mFlags & AUDIO_OUTPUT_FLAG_BIT_PERFECT);
+
+ // Start bit-perfect playback
+ getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,
+ bitPerfectSampleRate, AUDIO_OUTPUT_FLAG_NONE, &bitPerfectOutput, &bitPerfectPortId,
+ mediaAttr, AUDIO_SESSION_NONE, uid, &isBitPerfect);
+ status_t status = mManager->startOutput(bitPerfectPortId);
+ if (status == DEAD_OBJECT) {
+ getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,
+ bitPerfectSampleRate, AUDIO_OUTPUT_FLAG_NONE, &bitPerfectOutput, &bitPerfectPortId,
+ mediaAttr, AUDIO_SESSION_NONE, uid, &isBitPerfect);
+ status = mManager->startOutput(bitPerfectPortId);
+ }
+ EXPECT_EQ(NO_ERROR, status);
+ EXPECT_TRUE(isBitPerfect);
+ EXPECT_NE(AUDIO_IO_HANDLE_NONE, bitPerfectOutput);
+ const auto bitPerfectOutputDesc = mManager->getOutputs().valueFor(bitPerfectOutput);
+ EXPECT_NE(nullptr, bitPerfectOutputDesc);
+ EXPECT_EQ(AUDIO_OUTPUT_FLAG_BIT_PERFECT,
+ bitPerfectOutputDesc->mFlags & AUDIO_OUTPUT_FLAG_BIT_PERFECT);
+
+ // If the playback is from preferred mixer attributes owner but the request doesn't match
+ // preferred mixer attributes, it will not be bit-perfect.
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr, AUDIO_SESSION_NONE,
+ uid, &isBitPerfect);
+ EXPECT_FALSE(isBitPerfect);
+ EXPECT_EQ(bitPerfectOutput, output);
+
+ // When bit-perfect playback is active, all other playback will be routed to bit-perfect output.
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr, AUDIO_SESSION_NONE,
+ anotherUid, &isBitPerfect);
+ EXPECT_FALSE(isBitPerfect);
+ EXPECT_EQ(bitPerfectOutput, output);
+
+ // When configuration matches preferred mixer attributes, which is bit-perfect, but the client
+ // is not the owner of preferred mixer attributes, the playback will not be bit-perfect.
+ getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,
+ bitPerfectSampleRate, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr,
+ AUDIO_SESSION_NONE, anotherUid, &isBitPerfect);
+ EXPECT_FALSE(isBitPerfect);
+ EXPECT_EQ(bitPerfectOutput, output);
+
+ EXPECT_EQ(NO_ERROR,
+ mManager->clearPreferredMixerAttributes(&mediaAttr, usbPortId, uid));
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_OUT_USB_DEVICE,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ "", "", AUDIO_FORMAT_LDAC));
+}
+
class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
protected:
void TearDown() override;
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index c937d3a..2eb771d 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -54,7 +54,7 @@
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
- <mixPort name="hifi_output" role="source"/>
+ <mixPort name="hifi_output" role="source" flags="AUDIO_OUTPUT_FLAG_BIT_PERFECT"/>
</mixPorts>
<devicePorts>
<devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 1e6524f..7b1759e 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -95,6 +95,12 @@
"hidl/HidlCameraDeviceUser.cpp",
"hidl/HidlCameraService.cpp",
"hidl/Utils.cpp",
+ "aidl/AidlCameraDeviceCallbacks.cpp",
+ "aidl/AidlCameraDeviceUser.cpp",
+ "aidl/AidlCameraService.cpp",
+ "aidl/AidlCameraServiceListener.cpp",
+ "aidl/AidlUtils.cpp",
+ "aidl/DeathPipe.cpp",
"utils/CameraServiceProxyWrapper.cpp",
"utils/CameraThreadState.cpp",
"utils/CameraTraces.cpp",
@@ -151,6 +157,9 @@
"android.frameworks.cameraservice.service@2.2",
"android.frameworks.cameraservice.device@2.0",
"android.frameworks.cameraservice.device@2.1",
+ "android.frameworks.cameraservice.common-V1-ndk",
+ "android.frameworks.cameraservice.service-V1-ndk",
+ "android.frameworks.cameraservice.device-V1-ndk",
"android.hardware.camera.common@1.0",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.5",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 0213623..caa1750 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -33,6 +33,7 @@
#include <android/hardware/ICamera.h>
#include <android/hardware/ICameraClient.h>
+#include <aidl/AidlCameraService.h>
#include <android-base/macros.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
@@ -88,6 +89,7 @@
using binder::Status;
using namespace camera3;
using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService;
+using frameworks::cameraservice::service::implementation::AidlCameraService;
using hardware::ICamera;
using hardware::ICameraClient;
using hardware::ICameraServiceListener;
@@ -196,6 +198,10 @@
__FUNCTION__);
}
+ if (!AidlCameraService::registerService(this)) {
+ ALOGE("%s: Failed to register default AIDL VNDK CameraService", __FUNCTION__);
+ }
+
// This needs to be last call in this function, so that it's as close to
// ServiceManager::addService() as possible.
mCameraServiceProxyWrapper->pingCameraServiceProxy();
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp
new file mode 100644
index 0000000..4c6d6f6
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2022 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 "AidlCameraDeviceCallbacks"
+
+#include <aidl/AidlCameraDeviceCallbacks.h>
+#include <aidl/AidlUtils.h>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <hidl/Utils.h>
+#include <utility>
+
+namespace android::frameworks::cameraservice::device::implementation {
+
+// VNDK classes
+using SCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using SCaptureResultExtras =
+ ::aidl::android::frameworks::cameraservice::device::CaptureResultExtras;
+using SPhysicalCaptureResultInfo =
+ ::aidl::android::frameworks::cameraservice::device::PhysicalCaptureResultInfo;
+using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
+// NDK classes
+using UCaptureResultExtras = ::android::hardware::camera2::impl::CaptureResultExtras;
+using UPhysicalCaptureResultInfo = ::android::hardware::camera2::impl::PhysicalCaptureResultInfo;
+
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::filterVndkKeys;
+
+const char *AidlCameraDeviceCallbacks::kResultKey = "CaptureResult";
+
+
+bool AidlCameraDeviceCallbacks::initializeLooper(int vndkVersion) {
+ mCbLooper = new ALooper;
+ mCbLooper->setName("cs-looper");
+ status_t err = mCbLooper->start(/*runOnCallingThread*/ false, /*canCallJava*/ false,
+ PRIORITY_DEFAULT);
+ if (err !=OK) {
+ ALOGE("Unable to start camera device callback looper");
+ return false;
+ }
+ mHandler = new CallbackHandler(this, vndkVersion);
+ mCbLooper->registerHandler(mHandler);
+ return true;
+}
+
+AidlCameraDeviceCallbacks::AidlCameraDeviceCallbacks(
+ const std::shared_ptr<SICameraDeviceCallback>& base):
+ mBase(base), mDeathPipe(this, base->asBinder()) {}
+
+AidlCameraDeviceCallbacks::~AidlCameraDeviceCallbacks() {
+ if (mCbLooper != nullptr) {
+ if (mHandler != nullptr) {
+ mCbLooper->unregisterHandler(mHandler->id());
+ }
+ mCbLooper->stop();
+ }
+ mCbLooper.clear();
+ mHandler.clear();
+}
+
+binder::Status AidlCameraDeviceCallbacks::onDeviceError(
+ int32_t errorCode, const CaptureResultExtras& resultExtras) {
+ using hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+ SCaptureResultExtras cre = convertToAidl(resultExtras);
+ auto ret = mBase->onDeviceError(convertToAidl(errorCode), cre);
+ LOG_STATUS_ERROR_IF_NOT_OK(ret, "onDeviceError")
+ return binder::Status::ok();
+}
+
+binder::Status AidlCameraDeviceCallbacks::onDeviceIdle() {
+ auto ret = mBase->onDeviceIdle();
+ LOG_STATUS_ERROR_IF_NOT_OK(ret, "onDeviceIdle")
+ return binder::Status::ok();
+}
+
+binder::Status AidlCameraDeviceCallbacks::onCaptureStarted(
+ const CaptureResultExtras& resultExtras, int64_t timestamp) {
+ using hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+ SCaptureResultExtras hCaptureResultExtras = convertToAidl(resultExtras);
+ auto ret = mBase->onCaptureStarted(hCaptureResultExtras, timestamp);
+ LOG_STATUS_ERROR_IF_NOT_OK(ret, "onCaptureStarted")
+ return binder::Status::ok();
+}
+
+void AidlCameraDeviceCallbacks::convertResultMetadataToAidl(const camera_metadata_t* src,
+ SCaptureMetadataInfo* dst) {
+ // First try writing to fmq.
+ size_t metadata_size = get_camera_metadata_size(src);
+ if ((metadata_size > 0) &&
+ (mCaptureResultMetadataQueue->availableToWrite() > 0)) {
+ if (mCaptureResultMetadataQueue->write((int8_t *)src, metadata_size)) {
+ dst->set<SCaptureMetadataInfo::fmqMetadataSize>(metadata_size);
+ } else {
+ ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__);
+ SCameraMetadata metadata;
+ hardware::cameraservice::utils::conversion::aidl::cloneToAidl(src, &metadata);
+ dst->set<SCaptureMetadataInfo::metadata>(std::move(metadata));
+ }
+ }
+}
+
+void AidlCameraDeviceCallbacks::CallbackHandler::onMessageReceived(const sp<AMessage> &msg) {
+ sp<RefBase> obj = nullptr;
+ sp<ResultWrapper> resultWrapper = nullptr;
+ bool found = false;
+ switch (msg->what()) {
+ case kWhatResultReceived:
+ found = msg->findObject(kResultKey, &obj);
+ if (!found || obj == nullptr) {
+ ALOGE("Cannot find result object in callback message");
+ return;
+ }
+ resultWrapper = static_cast<ResultWrapper*>(obj.get());
+ processResultMessage(resultWrapper);
+ break;
+ default:
+ ALOGE("Unknown callback sent");
+ break;
+ }
+ }
+
+void AidlCameraDeviceCallbacks::CallbackHandler::processResultMessage(
+ sp<ResultWrapper> &resultWrapper) {
+ sp<AidlCameraDeviceCallbacks> converter = mConverter.promote();
+ if (converter == nullptr) {
+ ALOGE("Callback wrapper has died, result callback cannot be made");
+ return;
+ }
+ CameraMetadataNative &result = resultWrapper->mResult;
+ auto resultExtras = resultWrapper->mResultExtras;
+ SCaptureResultExtras convResultExtras =
+ hardware::cameraservice::utils::conversion::aidl::convertToAidl(resultExtras);
+
+ // Convert Metadata into HCameraMetadata;
+ SCaptureMetadataInfo captureMetadataInfo;
+ if (filterVndkKeys(mVndkVersion, result, /*isStatic*/false) != OK) {
+ ALOGE("%s: filtering vndk keys from result failed, not sending onResultReceived callback",
+ __FUNCTION__);
+ return;
+ }
+ const camera_metadata_t *rawMetadata = result.getAndLock();
+ converter->convertResultMetadataToAidl(rawMetadata, &captureMetadataInfo);
+ result.unlock(rawMetadata);
+
+ auto &physicalCaptureResultInfos = resultWrapper->mPhysicalCaptureResultInfos;
+ std::vector<SPhysicalCaptureResultInfo> stableCaptureResInfo =
+ convertToAidl(physicalCaptureResultInfos, converter->mCaptureResultMetadataQueue);
+ auto ret = converter->mBase->onResultReceived(captureMetadataInfo,
+ convResultExtras,
+ stableCaptureResInfo);
+
+ LOG_STATUS_ERROR_IF_NOT_OK(ret, "OnResultReceived")
+}
+
+binder::Status AidlCameraDeviceCallbacks::onResultReceived(
+ const CameraMetadataNative& result,
+ const UCaptureResultExtras& resultExtras,
+ const ::std::vector<UPhysicalCaptureResultInfo>& physicalCaptureResultInfos) {
+ // Wrap CameraMetadata, resultExtras and physicalCaptureResultInfos in on
+ // sp<RefBase>-able structure and post it.
+ sp<ResultWrapper> resultWrapper = new ResultWrapper(const_cast<CameraMetadataNative &>(result),
+ resultExtras, physicalCaptureResultInfos);
+ sp<AMessage> msg = new AMessage(kWhatResultReceived, mHandler);
+ msg->setObject(kResultKey, resultWrapper);
+ msg->post();
+ return binder::Status::ok();
+}
+
+binder::Status AidlCameraDeviceCallbacks::onPrepared(int32_t) {
+ // not implemented
+ return binder::Status::ok();
+}
+
+binder::Status AidlCameraDeviceCallbacks::onRepeatingRequestError(
+ int64_t lastFrameNumber,
+ int32_t repeatingRequestId) {
+ auto ret =
+ mBase->onRepeatingRequestError(lastFrameNumber, repeatingRequestId);
+ LOG_STATUS_ERROR_IF_NOT_OK(ret, "onRepeatingRequestError")
+ return binder::Status::ok();
+}
+binder::Status AidlCameraDeviceCallbacks::onRequestQueueEmpty() {
+ // not implemented
+ return binder::Status::ok();
+}
+
+status_t AidlCameraDeviceCallbacks::linkToDeath(const sp<DeathRecipient>& recipient,
+ void* cookie, uint32_t flags) {
+ return mDeathPipe.linkToDeath(recipient, cookie, flags);
+}
+status_t AidlCameraDeviceCallbacks::unlinkToDeath(const wp<DeathRecipient>& recipient,
+ void* cookie,
+ uint32_t flags,
+ wp<DeathRecipient>* outRecipient) {
+ return mDeathPipe.unlinkToDeath(recipient, cookie, flags, outRecipient);
+}
+
+} // namespace android::frameworks::cameraservice::device::implementation
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h
new file mode 100644
index 0000000..5cff5b3
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceCallbacks.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICECALLBACKS_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICECALLBACKS_H_
+
+#include <CameraService.h>
+#include <aidl/DeathPipe.h>
+#include <aidl/android/frameworks/cameraservice/device/BnCameraDeviceCallback.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureMetadataInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCaptureResultInfo.h>
+#include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
+#include <fmq/AidlMessageQueue.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <mutex>
+#include <thread>
+#include <utility>
+
+namespace android::frameworks::cameraservice::device::implementation {
+
+// VNDK classes
+using SCaptureMetadataInfo = ::aidl::android::frameworks::cameraservice::device::CaptureMetadataInfo;
+using SICameraDeviceCallback =
+ ::aidl::android::frameworks::cameraservice::device::ICameraDeviceCallback;
+// NDK classes
+using UBnCameraDeviceCallbacks = ::android::hardware::camera2::BnCameraDeviceCallbacks;
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::frameworks::cameraservice::utils::DeathPipe;
+using ::android::hardware::camera2::impl::CameraMetadataNative;
+
+using CaptureResultMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+
+class AidlCameraDeviceCallbacks : public UBnCameraDeviceCallbacks {
+ public:
+ explicit AidlCameraDeviceCallbacks(const std::shared_ptr<SICameraDeviceCallback>& base);
+
+ ~AidlCameraDeviceCallbacks() override;
+
+ bool initializeLooper(int vndkVersion);
+
+ binder::Status onDeviceError(int32_t errorCode,
+ const CaptureResultExtras& resultExtras) override;
+
+ binder::Status onDeviceIdle() override;
+
+ binder::Status onCaptureStarted(const CaptureResultExtras& resultExtras,
+ int64_t timestamp) override;
+
+ binder::Status onResultReceived(
+ const CameraMetadataNative& result, const CaptureResultExtras& resultExtras,
+ const std::vector<PhysicalCaptureResultInfo>& physicalCaptureResultInfos) override;
+
+ binder::Status onPrepared(int32_t streamId) override;
+
+ binder::Status onRepeatingRequestError(int64_t lastFrameNumber,
+ int32_t repeatingRequestId) override;
+
+ binder::Status onRequestQueueEmpty() 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,
+ wp<DeathRecipient>* outRecipient) override;
+
+ void setCaptureResultMetadataQueue(std::shared_ptr<CaptureResultMetadataQueue> metadataQueue) {
+ mCaptureResultMetadataQueue = std::move(metadataQueue);
+ }
+
+ private:
+ // Wrapper struct so that parameters to onResultReceived callback may be
+ // sent through an AMessage.
+ struct ResultWrapper : public RefBase {
+ CameraMetadataNative mResult;
+ CaptureResultExtras mResultExtras;
+ std::vector<PhysicalCaptureResultInfo> mPhysicalCaptureResultInfos;
+
+ ResultWrapper(CameraMetadataNative &result,
+ CaptureResultExtras resultExtras,
+ std::vector<PhysicalCaptureResultInfo> physicalCaptureResultInfos) :
+ // TODO: make this std::movable
+ mResult(result),
+ mResultExtras(std::move(resultExtras)),
+ mPhysicalCaptureResultInfos(std::move(physicalCaptureResultInfos)) { }
+ };
+
+ struct CallbackHandler : public AHandler {
+ public:
+ void onMessageReceived(const sp<AMessage> &msg) override;
+ CallbackHandler(AidlCameraDeviceCallbacks *converter, int vndkVersion) :
+ mConverter(converter), mVndkVersion(vndkVersion) { }
+ private:
+ void processResultMessage(sp<ResultWrapper> &resultWrapper);
+ wp<AidlCameraDeviceCallbacks> mConverter = nullptr;
+ int mVndkVersion = -1;
+ };
+
+ void convertResultMetadataToAidl(const camera_metadata * src, SCaptureMetadataInfo * dst);
+ enum {
+ kWhatResultReceived,
+ };
+
+ static const char *kResultKey;
+
+ private:
+ std::shared_ptr<SICameraDeviceCallback> mBase;
+ std::shared_ptr<CaptureResultMetadataQueue> mCaptureResultMetadataQueue = nullptr;
+ sp<CallbackHandler> mHandler = nullptr;
+ sp<ALooper> mCbLooper = nullptr;
+
+ // Pipes death subscription from current NDK interface to VNDK mBase.
+ // Should consume calls to linkToDeath and unlinkToDeath.
+ DeathPipe mDeathPipe;
+};
+
+} // namespace android::frameworks::cameraservice::device::implementation
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICECALLBACKS_H_
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
new file mode 100644
index 0000000..d9ec0b6
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2022 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 "AidlCameraDeviceUser"
+
+#include "AidlCameraDeviceUser.h"
+#include <aidl/AidlUtils.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureMetadataInfo.h>
+
+namespace android::frameworks::cameraservice::device::implementation {
+
+// VNDK classes
+using SCaptureMetadataInfo = ::aidl::android::frameworks::cameraservice::device::CaptureMetadataInfo;
+// NDK classes
+using UOutputConfiguration = ::android::hardware::camera2::params::OutputConfiguration;
+using USessionConfiguration = ::android::hardware::camera2::params::SessionConfiguration;
+using UStatus = ::android::binder::Status;
+using USubmitInfo = ::android::hardware::camera2::utils::SubmitInfo;
+
+using ::android::CameraMetadata;
+using ::android::hardware::cameraservice::utils::conversion::aidl::cloneFromAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::cloneToAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertFromAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+using ::ndk::ScopedAStatus;
+
+namespace {
+constexpr int32_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
+constexpr int32_t CAMERA_RESULT_METADATA_QUEUE_SIZE = 1 << 20 /* 1 MB */;
+
+inline ScopedAStatus fromSStatus(const SStatus& s) {
+ return s == SStatus::NO_ERROR ? ScopedAStatus::ok()
+ : ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(s));
+}
+inline ScopedAStatus fromUStatus(const UStatus& status) {
+ return status.isOk() ? ScopedAStatus::ok() : fromSStatus(convertToAidl(status));
+}
+} // anonymous namespace
+
+AidlCameraDeviceUser::AidlCameraDeviceUser(const sp<UICameraDeviceUser>& deviceRemote):
+ mDeviceRemote(deviceRemote) {
+ mInitSuccess = initDevice();
+}
+bool AidlCameraDeviceUser::initDevice() {
+ // TODO: Get request and result metadata queue size from a system property.
+ int32_t reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE;
+
+ mCaptureRequestMetadataQueue =
+ std::make_unique<CaptureRequestMetadataQueue>(static_cast<size_t>(reqFMQSize),
+ false /* non blocking */);
+ if (!mCaptureRequestMetadataQueue->isValid()) {
+ ALOGE("%s: invalid request fmq", __FUNCTION__);
+ return false;
+ }
+
+ int32_t resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE;
+ mCaptureResultMetadataQueue =
+ std::make_shared<CaptureResultMetadataQueue>(static_cast<size_t>(resFMQSize),
+ false /* non blocking */);
+ if (!mCaptureResultMetadataQueue->isValid()) {
+ ALOGE("%s: invalid result fmq", __FUNCTION__);
+ return false;
+ }
+ return true;
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::getCaptureRequestMetadataQueue(
+ MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) {
+ if (mInitSuccess) {
+ *_aidl_return = mCaptureRequestMetadataQueue->dupeDesc();
+ }
+ return ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::getCaptureResultMetadataQueue(
+ MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) {
+ if (mInitSuccess) {
+ *_aidl_return = mCaptureResultMetadataQueue->dupeDesc();
+ }
+ return ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::submitRequestList(
+ const std::vector<SCaptureRequest>& in_requestList, bool in_isRepeating,
+ SSubmitInfo* _aidl_return) {
+ USubmitInfo submitInfo;
+ std::vector<UCaptureRequest> requests;
+ for (const auto& req: in_requestList) {
+ requests.emplace_back();
+ if (!convertRequestFromAidl(req, &requests.back())) {
+ ALOGE("%s: Failed to convert AIDL CaptureRequest.", __FUNCTION__);
+ return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
+ }
+ }
+ UStatus ret = mDeviceRemote->submitRequestList(requests,
+ in_isRepeating, &submitInfo);
+ if (!ret.isOk()) {
+ ALOGE("%s: Failed submitRequestList to cameraservice: %s",
+ __FUNCTION__, ret.toString8().string());
+ return fromUStatus(ret);
+ }
+ mRequestId = submitInfo.mRequestId;
+ convertToAidl(submitInfo, _aidl_return);
+ return ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::cancelRepeatingRequest(int64_t* _aidl_return) {
+ UStatus ret = mDeviceRemote->cancelRequest(mRequestId, _aidl_return);
+ return fromUStatus(ret);
+}
+
+ScopedAStatus AidlCameraDeviceUser::beginConfigure() {
+ UStatus ret = mDeviceRemote->beginConfigure();
+ return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::endConfigure(SStreamConfigurationMode in_operatingMode,
+ const SCameraMetadata& in_sessionParams,
+ int64_t in_startTimeNs) {
+ CameraMetadata metadata;
+ if (!cloneFromAidl(in_sessionParams, &metadata)) {
+ return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
+ }
+
+ std::vector<int32_t> offlineStreamIds;
+ UStatus ret = mDeviceRemote->endConfigure(convertFromAidl(in_operatingMode),
+ metadata, in_startTimeNs,
+ &offlineStreamIds);
+ return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::createStream(
+ const SOutputConfiguration& in_outputConfiguration, int32_t* _aidl_return) {
+ UOutputConfiguration outputConfig = convertFromAidl(in_outputConfiguration);
+ int32_t newStreamId;
+ UStatus ret = mDeviceRemote->createStream(outputConfig, &newStreamId);
+ if (!ret.isOk()) {
+ ALOGE("%s: Failed to create stream: %s", __FUNCTION__, ret.toString8().string());
+ }
+ *_aidl_return = newStreamId;
+ return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::createDefaultRequest(STemplateId in_templateId,
+ SCameraMetadata* _aidl_return) {
+ CameraMetadata metadata;
+ UStatus ret = mDeviceRemote->createDefaultRequest(convertFromAidl(in_templateId),
+ &metadata);
+ if (!ret.isOk()) {
+ ALOGE("%s: Failed to create default request: %s", __FUNCTION__, ret.toString8().string());
+ return fromUStatus(ret);
+ }
+ const camera_metadata_t* rawMetadata = metadata.getAndLock();
+ cloneToAidl(rawMetadata, _aidl_return);
+ metadata.unlock(rawMetadata);
+ return ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::waitUntilIdle() {
+ UStatus ret = mDeviceRemote->waitUntilIdle();
+ return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::flush(int64_t* _aidl_return) {
+ UStatus ret = mDeviceRemote->flush(_aidl_return);
+ return fromUStatus(ret);
+}
+
+ndk::ScopedAStatus AidlCameraDeviceUser::updateOutputConfiguration(
+ int32_t in_streamId, const SOutputConfiguration& in_outputConfiguration) {
+ UOutputConfiguration outputConfig = convertFromAidl(in_outputConfiguration);
+ UStatus ret = mDeviceRemote->updateOutputConfiguration(in_streamId, outputConfig);
+ if (!ret.isOk()) {
+ ALOGE("%s: Failed to update output config for stream id: %d: %s",
+ __FUNCTION__, in_streamId, ret.toString8().string());
+ }
+ return fromUStatus(ret);
+}
+ndk::ScopedAStatus AidlCameraDeviceUser::isSessionConfigurationSupported(
+ const SSessionConfiguration& in_sessionConfiguration, bool* _aidl_return) {
+ USessionConfiguration sessionConfig = convertFromAidl(in_sessionConfiguration);
+ UStatus ret = mDeviceRemote->isSessionConfigurationSupported(sessionConfig,
+ _aidl_return);
+ return fromUStatus(ret);
+}
+ndk::ScopedAStatus AidlCameraDeviceUser::deleteStream(int32_t in_streamId) {
+ UStatus ret = mDeviceRemote->deleteStream(in_streamId);
+ return fromUStatus(ret);
+}
+ndk::ScopedAStatus AidlCameraDeviceUser::disconnect() {
+ UStatus ret = mDeviceRemote->disconnect();
+ return fromUStatus(ret);
+}
+bool AidlCameraDeviceUser::convertRequestFromAidl(
+ const SCaptureRequest& src, UCaptureRequest* dst) {
+ dst->mIsReprocess = false;
+ for (const auto& streamAndWindowId : src.streamAndWindowIds) {
+ dst->mStreamIdxList.push_back(streamAndWindowId.streamId);
+ dst->mSurfaceIdxList.push_back(streamAndWindowId.windowId);
+ }
+
+ return copyPhysicalCameraSettings(src.physicalCameraSettings,
+ &(dst->mPhysicalCameraSettings));
+}
+bool AidlCameraDeviceUser::copyPhysicalCameraSettings(
+ const std::vector<SPhysicalCameraSettings>& src,
+ std::vector<UCaptureRequest::PhysicalCameraSettings>* dst) {
+ bool converted = false;
+ for (auto &e : src) {
+ dst->emplace_back();
+ CaptureRequest::PhysicalCameraSettings &physicalCameraSetting =
+ dst->back();
+ physicalCameraSetting.id = e.id;
+
+ // Read the settings either from the fmq or straightaway from the
+ // request. We don't need any synchronization, since submitRequestList
+ // is guaranteed to be called serially by the client if it decides to
+ // use fmq.
+ if (e.settings.getTag() == SCaptureMetadataInfo::fmqMetadataSize) {
+ /**
+ * Get settings from the fmq.
+ */
+ SCameraMetadata settingsFmq;
+ int64_t metadataSize = e.settings.get<SCaptureMetadataInfo::fmqMetadataSize>();
+ settingsFmq.metadata.resize(metadataSize);
+ int8_t* metadataPtr = (int8_t*) settingsFmq.metadata.data();
+ bool read = mCaptureRequestMetadataQueue->read(metadataPtr,
+ metadataSize);
+ if (!read) {
+ ALOGE("%s capture request settings could't be read from fmq size", __FUNCTION__);
+ converted = false;
+ } else {
+ converted = cloneFromAidl(settingsFmq, &physicalCameraSetting.settings);
+ }
+ } else {
+ /**
+ * The settings metadata is contained in request settings field.
+ */
+ converted = cloneFromAidl(e.settings.get<SCaptureMetadataInfo::metadata>(),
+ &physicalCameraSetting.settings);
+ }
+ if (!converted) {
+ ALOGE("%s: Unable to convert physicalCameraSettings from HIDL to AIDL.", __FUNCTION__);
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace android::frameworks::cameraservice::device::implementation
\ No newline at end of file
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h
new file mode 100644
index 0000000..41a3f43
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICEUSER_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICEUSER_H_
+
+#include <CameraService.h>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/device/BnCameraDeviceUser.h>
+#include <aidl/android/frameworks/cameraservice/device/CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/device/OutputConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCameraSettings.h>
+#include <aidl/android/frameworks/cameraservice/device/SessionConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/StreamConfigurationMode.h>
+#include <aidl/android/frameworks/cameraservice/device/SubmitInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/TemplateId.h>
+#include <aidl/android/hardware/common/fmq/MQDescriptor.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include <fmq/AidlMessageQueue.h>
+#include <memory>
+
+namespace android::frameworks::cameraservice::device::implementation {
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using CaptureRequestMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+using CaptureResultMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+
+// Stable NDK classes
+using SBnCameraDeviceUser = ::aidl::android::frameworks::cameraservice::device::BnCameraDeviceUser;
+using SCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using SCaptureRequest = ::aidl::android::frameworks::cameraservice::device::CaptureRequest;
+using SOutputConfiguration =
+ ::aidl::android::frameworks::cameraservice::device::OutputConfiguration;
+using SPhysicalCameraSettings =
+ ::aidl::android::frameworks::cameraservice::device::PhysicalCameraSettings;
+using SSessionConfiguration =
+ ::aidl::android::frameworks::cameraservice::device::SessionConfiguration;
+using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
+using SStreamConfigurationMode =
+ ::aidl::android::frameworks::cameraservice::device::StreamConfigurationMode;
+using SSubmitInfo = ::aidl::android::frameworks::cameraservice::device::SubmitInfo;
+using STemplateId = ::aidl::android::frameworks::cameraservice::device::TemplateId;
+// Unstable NDK classes
+using UCaptureRequest= ::android::hardware::camera2::CaptureRequest;
+using UICameraDeviceUser = ::android::hardware::camera2::ICameraDeviceUser;
+
+static constexpr int32_t REQUEST_ID_NONE = -1;
+
+class AidlCameraDeviceUser final : public SBnCameraDeviceUser {
+ public:
+ explicit AidlCameraDeviceUser(const sp<UICameraDeviceUser> &deviceRemote);
+ ~AidlCameraDeviceUser() override = default;
+
+ ndk::ScopedAStatus beginConfigure() override;
+ ndk::ScopedAStatus cancelRepeatingRequest(int64_t* _aidl_return) override;
+ ndk::ScopedAStatus createDefaultRequest(STemplateId in_templateId,
+ SCameraMetadata* _aidl_return) override;
+ ndk::ScopedAStatus createStream(const SOutputConfiguration& in_outputConfiguration,
+ int32_t* _aidl_return) override;
+ ndk::ScopedAStatus deleteStream(int32_t in_streamId) override;
+ ndk::ScopedAStatus disconnect() override;
+ ndk::ScopedAStatus endConfigure(SStreamConfigurationMode in_operatingMode,
+ const SCameraMetadata& in_sessionParams,
+ int64_t in_startTimeNs) override;
+ ndk::ScopedAStatus flush(int64_t* _aidl_return) override;
+ ndk::ScopedAStatus getCaptureRequestMetadataQueue(
+ MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) override;
+ ndk::ScopedAStatus getCaptureResultMetadataQueue(
+ MQDescriptor<int8_t, SynchronizedReadWrite>* _aidl_return) override;
+ ndk::ScopedAStatus isSessionConfigurationSupported(
+ const SSessionConfiguration& in_sessionConfiguration, bool* _aidl_return) override;
+ ndk::ScopedAStatus submitRequestList(const std::vector<SCaptureRequest>& in_requestList,
+ bool in_isRepeating, SSubmitInfo* _aidl_return) override;
+ ndk::ScopedAStatus updateOutputConfiguration(
+ int32_t in_streamId, const SOutputConfiguration& in_outputConfiguration) override;
+ ndk::ScopedAStatus waitUntilIdle() override;
+
+ [[nodiscard]] bool initStatus() const { return mInitSuccess; }
+
+ std::shared_ptr<CaptureResultMetadataQueue> getCaptureResultMetadataQueue() {
+ return mCaptureResultMetadataQueue;
+ }
+
+ private:
+ bool initDevice();
+
+ bool convertRequestFromAidl(const SCaptureRequest &src, UCaptureRequest *dst);
+ bool copyPhysicalCameraSettings(const std::vector<SPhysicalCameraSettings> &src,
+ std::vector<CaptureRequest::PhysicalCameraSettings> *dst);
+
+ const sp<UICameraDeviceUser> mDeviceRemote;
+ std::unique_ptr<CaptureRequestMetadataQueue> mCaptureRequestMetadataQueue = nullptr;
+ std::shared_ptr<CaptureResultMetadataQueue> mCaptureResultMetadataQueue = nullptr;
+ bool mInitSuccess = false;
+ int32_t mRequestId = REQUEST_ID_NONE;
+};
+
+} // namespace android::frameworks::cameraservice::device::implementation
+
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERADEVICEUSER_H_
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.cpp b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
new file mode 100644
index 0000000..4232a81
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2022 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 "AidlCameraService"
+
+#include "AidlCameraService.h"
+#include <aidl/AidlCameraDeviceCallbacks.h>
+#include <aidl/AidlCameraDeviceUser.h>
+#include <aidl/AidlCameraServiceListener.h>
+#include <aidl/AidlUtils.h>
+#include <aidl/android/frameworks/cameraservice/common/CameraMetadataType.h>
+#include <android-base/properties.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
+#include <binder/Status.h>
+#include <hidl/HidlTransportSupport.h>
+
+namespace android::frameworks::cameraservice::service::implementation {
+
+using ::android::frameworks::cameraservice::device::implementation::AidlCameraDeviceCallbacks;
+using ::android::frameworks::cameraservice::device::implementation::AidlCameraDeviceUser;
+using ::android::hardware::cameraservice::utils::conversion::aidl::areBindersEqual;
+using ::android::hardware::cameraservice::utils::conversion::aidl::cloneToAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertToAidl;
+using ::android::hardware::cameraservice::utils::conversion::aidl::filterVndkKeys;
+using ::ndk::ScopedAStatus;
+
+// VNDK classes
+using SCameraMetadataType = ::aidl::android::frameworks::cameraservice::common::CameraMetadataType;
+using SVendorTag = ::aidl::android::frameworks::cameraservice::common::VendorTag;
+using SVendorTagSection = ::aidl::android::frameworks::cameraservice::common::VendorTagSection;
+// NDK classes
+using UICameraService = ::android::hardware::ICameraService;
+using UStatus = ::android::binder::Status;
+
+namespace {
+inline ScopedAStatus fromSStatus(const SStatus& s) {
+ return s == SStatus::NO_ERROR ? ScopedAStatus::ok()
+ : ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(s));
+}
+inline ScopedAStatus fromUStatus(const UStatus& s) {
+ return s.isOk() ? ScopedAStatus::ok() : fromSStatus(convertToAidl(s));
+}
+} // anonymous namespace
+
+std::shared_ptr<AidlCameraService> kCameraService;
+
+bool AidlCameraService::registerService(::android::CameraService* cameraService) {
+ kCameraService = SharedRefBase::make<AidlCameraService>(cameraService);
+ std::string serviceName = SBnCameraService::descriptor;
+ serviceName += "/default";
+ bool isDeclared = AServiceManager_isDeclared(serviceName.c_str());
+ if (!isDeclared) {
+ ALOGI("%s: AIDL vndk not declared.", __FUNCTION__);
+ return false;
+ }
+
+ binder_exception_t registered = AServiceManager_addService(
+ kCameraService->asBinder().get(), serviceName.c_str());
+ ALOGE_IF(registered != EX_NONE,
+ "%s: AIDL VNDK declared, but failed to register service: %d",
+ __FUNCTION__, registered);
+ return registered == EX_NONE;
+}
+
+AidlCameraService::AidlCameraService(::android::CameraService* cameraService):
+ mCameraService(cameraService) {
+ mVndkVersion = base::GetIntProperty("ro.vndk.version", __ANDROID_API_FUTURE__);
+}
+ScopedAStatus AidlCameraService::getCameraCharacteristics(const std::string& in_cameraId,
+ SCameraMetadata* _aidl_return) {
+ if (_aidl_return == nullptr) { return fromSStatus(SStatus::ILLEGAL_ARGUMENT); }
+
+ ::android::CameraMetadata cameraMetadata;
+ UStatus ret = mCameraService->getCameraCharacteristics(String16(in_cameraId.c_str()),
+ mVndkVersion,
+ /* overrideToPortrait= */ false,
+ &cameraMetadata);
+ if (!ret.isOk()) {
+ if (ret.exceptionCode() != EX_SERVICE_SPECIFIC) {
+ ALOGE("%s: Transaction error when getting camera characteristics"
+ " from camera service: %d.",
+ __FUNCTION__ , ret.exceptionCode());
+ return fromUStatus(ret);
+ }
+ switch (ret.serviceSpecificErrorCode()) {
+ case UICameraService::ERROR_ILLEGAL_ARGUMENT:
+ ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, in_cameraId.c_str());
+ return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
+ default:
+ ALOGE("Get camera characteristics from camera service failed: %s",
+ ret.toString8().string());
+ return fromUStatus(ret);
+ }
+ }
+
+ if (filterVndkKeys(mVndkVersion, cameraMetadata) != OK) {
+ ALOGE("%s: Unable to filter vndk metadata keys for version %d",
+ __FUNCTION__, mVndkVersion);
+ return fromSStatus(SStatus::UNKNOWN_ERROR);
+ }
+
+ const camera_metadata_t* rawMetadata = cameraMetadata.getAndLock();
+ cloneToAidl(rawMetadata, _aidl_return);
+ cameraMetadata.unlock(rawMetadata);
+
+ 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) {
+ // Here, we first get NDK ICameraDeviceUser from mCameraService, then save
+ // that interface in the newly created AidlCameraDeviceUser impl class.
+ if (mCameraService == nullptr) {
+ return fromSStatus(SStatus::UNKNOWN_ERROR);
+ }
+ sp<hardware::camera2::ICameraDeviceUser> unstableDevice = nullptr;
+ // Create a hardware::camera2::ICameraDeviceCallback object which internally
+ // calls callback functions passed through hCallback.
+ sp<AidlCameraDeviceCallbacks> hybridCallbacks = new AidlCameraDeviceCallbacks(in_callback);
+ if (!hybridCallbacks->initializeLooper(mVndkVersion)) {
+ ALOGE("Unable to handle callbacks on device, cannot connect");
+ return fromSStatus(SStatus::UNKNOWN_ERROR);
+ }
+ sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
+ binder::Status serviceRet = mCameraService->connectDevice(
+ callbacks,
+ String16(in_cameraId.c_str()),
+ String16(""),
+ /* clientFeatureId= */{},
+ hardware::ICameraService::USE_CALLING_UID,
+ /* scoreOffset= */ 0,
+ /* targetSdkVersion= */ __ANDROID_API_FUTURE__,
+ /* overrideToPortrait= */ false,
+ &unstableDevice);
+ if (!serviceRet.isOk()) {
+ ALOGE("%s: Unable to connect to camera device: %s", __FUNCTION__,
+ serviceRet.toString8().c_str());
+ return fromUStatus(serviceRet);
+ }
+
+ // Now we create a AidlCameraDeviceUser class, store the unstableDevice in it,
+ // and return that back. All calls on that interface will be forwarded to
+ // the NDK AIDL interface.
+ std::shared_ptr<AidlCameraDeviceUser> stableDevice =
+ ndk::SharedRefBase::make<AidlCameraDeviceUser>(unstableDevice);
+ if (!stableDevice->initStatus()) {
+ ALOGE("%s: Unable to initialize camera device AIDL wrapper", __FUNCTION__);
+ return fromSStatus(SStatus::UNKNOWN_ERROR);
+ }
+ hybridCallbacks->setCaptureResultMetadataQueue(
+ stableDevice->getCaptureResultMetadataQueue());
+ *_aidl_return = stableDevice;
+ return ScopedAStatus::ok();
+}
+void AidlCameraService::addToListenerCacheLocked(
+ std::shared_ptr<SICameraServiceListener> stableCsListener,
+ sp<UICameraServiceListener> csListener) {
+ mListeners.emplace_back(std::make_pair(stableCsListener, csListener));
+}
+sp<UICameraServiceListener> AidlCameraService::searchListenerCacheLocked(
+ const std::shared_ptr<SICameraServiceListener>& listener, bool removeIfFound) {
+ // Go through the mListeners list and compare the listener with the VNDK AIDL
+ // listener registered.
+ if (listener == nullptr) {
+ return nullptr;
+ }
+
+ auto it = mListeners.begin();
+ sp<UICameraServiceListener> csListener = nullptr;
+ for (;it != mListeners.end(); it++) {
+ if (areBindersEqual(listener->asBinder(), it->first->asBinder())) {
+ break;
+ }
+ }
+ if (it != mListeners.end()) {
+ csListener = it->second;
+ if (removeIfFound) {
+ mListeners.erase(it);
+ }
+ }
+ return csListener;
+}
+ndk::ScopedAStatus AidlCameraService::addListener(
+ const std::shared_ptr<SICameraServiceListener>& in_listener,
+ std::vector<SCameraStatusAndId>* _aidl_return) {
+ std::vector<hardware::CameraStatus> cameraStatusAndIds{};
+ SStatus status = addListenerInternal(
+ in_listener, &cameraStatusAndIds);
+ if (status != SStatus::NO_ERROR) {
+ return fromSStatus(status);
+ }
+
+ // Convert cameraStatusAndIds to VNDK AIDL
+ convertToAidl(cameraStatusAndIds, _aidl_return);
+ return ScopedAStatus::ok();
+}
+SStatus AidlCameraService::addListenerInternal(
+ const std::shared_ptr<SICameraServiceListener>& listener,
+ std::vector<hardware::CameraStatus>* cameraStatusAndIds) {
+ if (mCameraService == nullptr) {
+ return SStatus::UNKNOWN_ERROR;
+ }
+ if (listener == nullptr || cameraStatusAndIds == nullptr) {
+ ALOGE("%s listener and cameraStatusAndIds must not be NULL", __FUNCTION__);
+ return SStatus::ILLEGAL_ARGUMENT;
+ }
+ sp<UICameraServiceListener> csListener = nullptr;
+ // Check the cache for previously registered callbacks
+ {
+ Mutex::Autolock l(mListenerListLock);
+ csListener = searchListenerCacheLocked(listener);
+ if (csListener == nullptr) {
+ // Wrap a listener with AidlCameraServiceListener and pass it to
+ // CameraService.
+ csListener = sp<AidlCameraServiceListener>::make(listener);
+ // Add to cache
+ addToListenerCacheLocked(listener, csListener);
+ } else {
+ ALOGE("%s: Trying to add a listener %p already registered",
+ __FUNCTION__, listener.get());
+ return SStatus::ILLEGAL_ARGUMENT;
+ }
+ }
+ binder::Status serviceRet =
+ mCameraService->addListenerHelper(csListener, cameraStatusAndIds, true);
+ if (!serviceRet.isOk()) {
+ ALOGE("%s: Unable to add camera device status listener", __FUNCTION__);
+ return convertToAidl(serviceRet);
+ }
+
+ cameraStatusAndIds->erase(std::remove_if(cameraStatusAndIds->begin(),
+ cameraStatusAndIds->end(),
+ [this](const hardware::CameraStatus& s) {
+ bool supportsHAL3 = false;
+ binder::Status sRet =
+ mCameraService->supportsCameraApi(String16(s.cameraId),
+ UICameraService::API_VERSION_2, &supportsHAL3);
+ return !sRet.isOk() || !supportsHAL3;
+ }), cameraStatusAndIds->end());
+
+ return SStatus::NO_ERROR;
+}
+ndk::ScopedAStatus AidlCameraService::removeListener(
+ const std::shared_ptr<SICameraServiceListener>& in_listener) {
+ if (in_listener == nullptr) {
+ ALOGE("%s listener must not be NULL", __FUNCTION__);
+ return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
+ }
+ sp<UICameraServiceListener> csListener = nullptr;
+ {
+ Mutex::Autolock l(mListenerListLock);
+ csListener = searchListenerCacheLocked(in_listener, /*removeIfFound*/true);
+ }
+ if (csListener != nullptr) {
+ mCameraService->removeListener(csListener);
+ } else {
+ ALOGE("%s Removing unregistered listener %p", __FUNCTION__, in_listener.get());
+ return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
+ }
+ return ScopedAStatus::ok();
+}
+ndk::ScopedAStatus AidlCameraService::getCameraVendorTagSections(
+ std::vector<SProviderIdAndVendorTagSections>* _aidl_return) {
+ sp<VendorTagDescriptorCache> gCache = VendorTagDescriptorCache::getGlobalVendorTagCache();
+ if (gCache == nullptr) {
+ return fromSStatus(SStatus::UNKNOWN_ERROR);
+ }
+
+ const std::unordered_map<metadata_vendor_id_t, sp<android::VendorTagDescriptor>>
+ &vendorIdsAndTagDescs = gCache->getVendorIdsAndTagDescriptors();
+ if (vendorIdsAndTagDescs.empty()) {
+ return fromSStatus(SStatus::UNKNOWN_ERROR);
+ }
+
+ std::vector<SProviderIdAndVendorTagSections>& tagIdAndVendorTagSections = *_aidl_return;
+ tagIdAndVendorTagSections.resize(vendorIdsAndTagDescs.size());
+ size_t j = 0;
+ for (auto &vendorIdAndTagDescs : vendorIdsAndTagDescs) {
+ std::vector<SVendorTagSection> vendorTagSections;
+ sp<VendorTagDescriptor> desc = vendorIdAndTagDescs.second;
+ const SortedVector<String8>* sectionNames = desc->getAllSectionNames();
+ size_t numSections = sectionNames->size();
+ std::vector<std::vector<SVendorTag>> tagsBySection(numSections);
+ int tagCount = desc->getTagCount();
+ if (tagCount <= 0) {
+ continue;
+ }
+ std::vector<uint32_t> tags(tagCount);
+ desc->getTagArray(tags.data());
+ for (int i = 0; i < tagCount; i++) {
+ SVendorTag vt;
+ vt.tagId = tags[i];
+ vt.tagName = desc->getTagName(tags[i]);
+ vt.tagType = (SCameraMetadataType) desc->getTagType(tags[i]);
+ ssize_t sectionIdx = desc->getSectionIndex(tags[i]);
+ tagsBySection[sectionIdx].push_back(vt);
+ }
+ vendorTagSections.resize(numSections);
+ for (size_t s = 0; s < numSections; s++) {
+ vendorTagSections[s].sectionName = (*sectionNames)[s].string();
+ vendorTagSections[s].tags = tagsBySection[s];
+ }
+ SProviderIdAndVendorTagSections & prvdrIdAndVendorTagSection =
+ tagIdAndVendorTagSections[j];
+ prvdrIdAndVendorTagSection.providerId = vendorIdAndTagDescs.first;
+ prvdrIdAndVendorTagSection.vendorTagSections = std::move(vendorTagSections);
+ j++;
+ }
+ return ScopedAStatus::ok();
+}
+
+} // namespace android::frameworks::cameraservice::service::implementation
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.h b/services/camera/libcameraservice/aidl/AidlCameraService.h
new file mode 100644
index 0000000..4c67ac7
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICE_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICE_H_
+
+#include <CameraService.h>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/service/BnCameraService.h>
+
+namespace android::frameworks::cameraservice::service::implementation {
+
+// VNDK classes
+using SBnCameraService = ::aidl::android::frameworks::cameraservice::service::BnCameraService;
+using SCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using SCameraStatusAndId = ::aidl::android::frameworks::cameraservice::service::CameraStatusAndId;
+using SICameraDeviceCallback =
+ ::aidl::android::frameworks::cameraservice::device::ICameraDeviceCallback;
+using SICameraDeviceUser = ::aidl::android::frameworks::cameraservice::device::ICameraDeviceUser;
+using SICameraServiceListener =
+ ::aidl::android::frameworks::cameraservice::service::ICameraServiceListener;
+using SProviderIdAndVendorTagSections =
+ ::aidl::android::frameworks::cameraservice::common::ProviderIdAndVendorTagSections;
+using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
+// NDK classes
+using UICameraServiceListener = ::android::hardware::ICameraServiceListener;
+
+class AidlCameraService: public SBnCameraService {
+ public:
+ static bool registerService(::android::CameraService* cameraService);
+
+ explicit AidlCameraService(::android::CameraService* cameraService);
+ ~AidlCameraService() override = default;
+ ndk::ScopedAStatus getCameraCharacteristics(const std::string& in_cameraId,
+ SCameraMetadata* _aidl_return) override;
+
+ ndk::ScopedAStatus connectDevice(const std::shared_ptr<SICameraDeviceCallback>& in_callback,
+ const std::string& in_cameraId,
+ std::shared_ptr<SICameraDeviceUser>* _aidl_return) override;
+
+ ndk::ScopedAStatus addListener(const std::shared_ptr<SICameraServiceListener>& in_listener,
+ std::vector<SCameraStatusAndId>* _aidl_return) override;
+
+ ndk::ScopedAStatus getCameraVendorTagSections(
+ std::vector<SProviderIdAndVendorTagSections>* _aidl_return) override;
+
+ ndk::ScopedAStatus removeListener(
+ const std::shared_ptr<SICameraServiceListener>& in_listener) override;
+
+ private:
+ void addToListenerCacheLocked(std::shared_ptr<SICameraServiceListener> stableCsListener,
+ sp<hardware::ICameraServiceListener> csListener);
+
+ sp<UICameraServiceListener> searchListenerCacheLocked(
+ const std::shared_ptr<SICameraServiceListener>& listener, bool removeIfFound = false);
+
+ SStatus addListenerInternal(const std::shared_ptr<SICameraServiceListener>& listener,
+ std::vector<hardware::CameraStatus>* cameraStatusAndIds);
+
+
+ ::android::CameraService* mCameraService;
+
+ Mutex mListenerListLock;
+ std::list<std::pair<std::shared_ptr<SICameraServiceListener>,
+ sp<UICameraServiceListener>>> mListeners;
+ int mVndkVersion = -1;
+
+};
+
+} // namespace android::frameworks::cameraservice::service::implementation
+
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICE_H_
diff --git a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp
new file mode 100644
index 0000000..e183063
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/AidlCameraServiceListener.h>
+#include <aidl/AidlUtils.h>
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraStatusAndId.h>
+
+namespace android::frameworks::cameraservice::service::implementation {
+
+using ::android::hardware::cameraservice::utils::conversion::aidl::convertCameraStatusToAidl;
+// VNDK classes
+using SCameraStatusAndId = ::aidl::android::frameworks::cameraservice::service::CameraStatusAndId;
+using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
+
+binder::Status AidlCameraServiceListener::onStatusChanged(
+ int32_t status, const ::android::String16& cameraId) {
+ SCameraDeviceStatus sStatus = convertCameraStatusToAidl(status);
+ std::string sCameraId = String8(cameraId).string();
+ auto ret = mBase->onStatusChanged(sStatus, sCameraId);
+ LOG_STATUS_ERROR_IF_NOT_OK(ret, "onStatusChanged")
+ return binder::Status::ok();
+}
+
+binder::Status AidlCameraServiceListener::onPhysicalCameraStatusChanged(
+ int32_t status, const ::android::String16& cameraId,
+ const ::android::String16& physicalCameraId) {
+ SCameraDeviceStatus sStatus = convertCameraStatusToAidl(status);
+ std::string sCameraId = String8(cameraId).string();
+ std::string sPhysicalCameraId = String8(physicalCameraId).string();
+
+ auto ret = mBase->onPhysicalCameraStatusChanged(sStatus, sCameraId, sPhysicalCameraId);
+ LOG_STATUS_ERROR_IF_NOT_OK(ret, "onPhysicalCameraStatusChanged")
+ return binder::Status::ok();
+}
+
+::android::binder::Status AidlCameraServiceListener::onTorchStatusChanged(
+ int32_t, const ::android::String16&) {
+ // We don't implement onTorchStatusChanged
+ return binder::Status::ok();
+}
+
+::android::binder::Status AidlCameraServiceListener::onTorchStrengthLevelChanged(
+ const ::android::String16&, int32_t) {
+ // We don't implement onTorchStrengthLevelChanged
+ return binder::Status::ok();
+}
+status_t AidlCameraServiceListener::linkToDeath(const sp<DeathRecipient>& recipient, void* cookie,
+ uint32_t flags) {
+ return mDeathPipe.linkToDeath(recipient, cookie, flags);
+}
+status_t AidlCameraServiceListener::unlinkToDeath(const wp<DeathRecipient>& recipient, void* cookie,
+ uint32_t flags,
+ wp<DeathRecipient>* outRecipient) {
+ return mDeathPipe.unlinkToDeath(recipient, cookie, flags, outRecipient);
+}
+
+} // namespace android::frameworks::cameraservice::service::implementation
diff --git a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
new file mode 100644
index 0000000..906dd8e
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICELISTENER_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICELISTENER_H_
+
+
+#include <aidl/DeathPipe.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraDeviceStatus.h>
+#include <aidl/android/frameworks/cameraservice/service/ICameraServiceListener.h>
+#include <android/hardware/BnCameraServiceListener.h>
+
+namespace android::frameworks::cameraservice::service::implementation {
+
+using ::android::frameworks::cameraservice::utils::DeathPipe;
+
+// VNDK classes
+using SCameraDeviceStatus = ::aidl::android::frameworks::cameraservice::service::CameraDeviceStatus;
+using SICameraServiceListener =
+ ::aidl::android::frameworks::cameraservice::service::ICameraServiceListener;
+// NDK classes
+using UBnCameraServiceListener = ::android::hardware::BnCameraServiceListener;
+
+/**
+ * A simple shim to pass calls from CameraService to VNDK client.
+ */
+class AidlCameraServiceListener : public UBnCameraServiceListener {
+ public:
+ AidlCameraServiceListener(const std::shared_ptr<SICameraServiceListener>& base):
+ mBase(base), mDeathPipe(this, base->asBinder()) {}
+
+ ~AidlCameraServiceListener() = default;
+
+ ::android::binder::Status onStatusChanged(int32_t status,
+ const ::android::String16& cameraId) override;
+ ::android::binder::Status onPhysicalCameraStatusChanged(int32_t status,
+ const ::android::String16& cameraId,
+ const ::android::String16& physicalCameraId) override;
+
+ ::android::binder::Status onTorchStatusChanged(
+ int32_t status, const ::android::String16& cameraId) override;
+ ::android::binder::Status onTorchStrengthLevelChanged(
+ const ::android::String16& cameraId, int32_t newStrengthLevel) override;
+ binder::Status onCameraAccessPrioritiesChanged() override {
+ // TODO: no implementation yet.
+ return binder::Status::ok();
+ }
+ binder::Status onCameraOpened(const ::android::String16& /*cameraId*/,
+ const ::android::String16& /*clientPackageId*/) override {
+ // empty implementation
+ return binder::Status::ok();
+ }
+ binder::Status onCameraClosed(const ::android::String16& /*cameraId*/) override {
+ // empty implementation
+ return binder::Status::ok();
+ }
+
+ 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,
+ wp<DeathRecipient>* outRecipient) override;
+
+ private:
+ std::shared_ptr<SICameraServiceListener> mBase;
+
+ // Pipes death subscription to current NDK AIDL interface to VNDK mBase.
+ // Should consume calls to linkToDeath and unlinkToDeath.
+ DeathPipe mDeathPipe;
+};
+
+} // android
+
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLCAMERASERVICELISTENER_H_
\ No newline at end of file
diff --git a/services/camera/libcameraservice/aidl/AidlUtils.cpp b/services/camera/libcameraservice/aidl/AidlUtils.cpp
new file mode 100644
index 0000000..1b8e53b
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlUtils.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2022 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 "AidlUtils"
+
+#include <aidl/AidlUtils.h>
+#include <aidl/VndkVersionMetadataTags.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <device3/Camera3StreamInterface.h>
+#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
+#include <mediautils/AImageReaderUtils.h>
+
+namespace android::hardware::cameraservice::utils::conversion::aidl {
+
+using aimg::AImageReader_getHGBPFromHandle;
+using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
+
+// Note: existing data in dst will be gone. Caller still owns the memory of src
+void cloneToAidl(const camera_metadata_t* src, SCameraMetadata* dst) {
+ if (src == nullptr) {
+ ALOGW("%s:attempt to convert empty metadata to AIDL", __FUNCTION__);
+ return;
+ }
+ size_t size = get_camera_metadata_size(src);
+ uint8_t* startPtr = (uint8_t*)src;
+ uint8_t* endPtr = startPtr + size;
+ dst->metadata.assign(startPtr, endPtr);
+}
+
+// The camera metadata here is cloned. Since we're reading metadata over
+// the binder we would need to clone it in order to avoid alignment issues.
+bool cloneFromAidl(const SCameraMetadata &src, CameraMetadata *dst) {
+ const camera_metadata_t *buffer =
+ reinterpret_cast<const camera_metadata_t*>(src.metadata.data());
+ size_t expectedSize = src.metadata.size();
+ if (buffer != nullptr) {
+ int res = validate_camera_metadata_structure(buffer, &expectedSize);
+ if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
+ *dst = buffer;
+ } else {
+ ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+ return false;
+ }
+ }
+ return true;
+}
+
+int32_t convertFromAidl(SStreamConfigurationMode streamConfigurationMode) {
+ switch (streamConfigurationMode) {
+ case SStreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE:
+ return camera2::ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE;
+ case SStreamConfigurationMode::NORMAL_MODE:
+ return camera2::ICameraDeviceUser::NORMAL_MODE;
+ default:
+ // TODO: Fix this
+ return camera2::ICameraDeviceUser::VENDOR_MODE_START;
+ }
+}
+
+UOutputConfiguration convertFromAidl(const SOutputConfiguration &src) {
+ std::vector<sp<IGraphicBufferProducer>> iGBPs;
+ auto &windowHandles = src.windowHandles;
+ iGBPs.reserve(windowHandles.size());
+
+ for (auto &handle : windowHandles) {
+ native_handle_t* nh = makeFromAidl(handle);
+ iGBPs.push_back(new H2BGraphicBufferProducer(AImageReader_getHGBPFromHandle(nh)));
+ native_handle_delete(nh);
+ }
+ String16 physicalCameraId16(src.physicalCameraId.c_str());
+ UOutputConfiguration outputConfiguration(
+ iGBPs, convertFromAidl(src.rotation), physicalCameraId16,
+ src.windowGroupId, OutputConfiguration::SURFACE_TYPE_UNKNOWN, 0, 0,
+ (windowHandles.size() > 1));
+ return outputConfiguration;
+}
+
+USessionConfiguration convertFromAidl(const SSessionConfiguration &src) {
+ USessionConfiguration sessionConfig(src.inputWidth, src.inputHeight,
+ src.inputFormat, static_cast<int>(src.operationMode));
+
+ for (const auto& os : src.outputStreams) {
+ UOutputConfiguration config = convertFromAidl(os);
+ sessionConfig.addOutputConfiguration(config);
+ }
+
+ return sessionConfig;
+}
+
+int convertFromAidl(SOutputConfiguration::Rotation rotation) {
+ switch(rotation) {
+ case SOutputConfiguration::Rotation::R270:
+ return android::camera3::CAMERA_STREAM_ROTATION_270;
+ case SOutputConfiguration::Rotation::R180:
+ return android::camera3::CAMERA_STREAM_ROTATION_180;
+ case SOutputConfiguration::Rotation::R90:
+ return android::camera3::CAMERA_STREAM_ROTATION_90;
+ case SOutputConfiguration::Rotation::R0:
+ default:
+ return android::camera3::CAMERA_STREAM_ROTATION_0;
+ }
+}
+
+int32_t convertFromAidl(STemplateId templateId) {
+ switch(templateId) {
+ case STemplateId::PREVIEW:
+ return camera2::ICameraDeviceUser::TEMPLATE_PREVIEW;
+ case STemplateId::STILL_CAPTURE:
+ return camera2::ICameraDeviceUser::TEMPLATE_STILL_CAPTURE;
+ case STemplateId::RECORD:
+ return camera2::ICameraDeviceUser::TEMPLATE_RECORD;
+ case STemplateId::VIDEO_SNAPSHOT:
+ return camera2::ICameraDeviceUser::TEMPLATE_VIDEO_SNAPSHOT;
+ case STemplateId::ZERO_SHUTTER_LAG:
+ return camera2::ICameraDeviceUser::TEMPLATE_ZERO_SHUTTER_LAG;
+ case STemplateId::MANUAL:
+ return camera2::ICameraDeviceUser::TEMPLATE_MANUAL;
+ }
+}
+
+void convertToAidl(const camera2::utils::SubmitInfo& submitInfo, SSubmitInfo* hSubmitInfo) {
+ hSubmitInfo->requestId = submitInfo.mRequestId;
+ hSubmitInfo->lastFrameNumber = submitInfo.mLastFrameNumber;
+}
+
+
+SStatus convertToAidl(const binder::Status &status) {
+ if (status.isOk()) {
+ return SStatus::NO_ERROR;
+ }
+ if (status.exceptionCode() != EX_SERVICE_SPECIFIC) {
+ return SStatus::UNKNOWN_ERROR;
+ }
+
+ switch (status.serviceSpecificErrorCode()) {
+ case hardware::ICameraService::ERROR_DISCONNECTED:
+ return SStatus::DISCONNECTED;
+ case hardware::ICameraService::ERROR_CAMERA_IN_USE:
+ return SStatus::CAMERA_IN_USE;
+ case hardware::ICameraService::ERROR_MAX_CAMERAS_IN_USE:
+ return SStatus::MAX_CAMERAS_IN_USE;
+ case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
+ return SStatus::ILLEGAL_ARGUMENT;
+ case hardware::ICameraService::ERROR_DEPRECATED_HAL:
+ // Should not reach here since we filtered legacy HALs earlier
+ return SStatus::DEPRECATED_HAL;
+ case hardware::ICameraService::ERROR_DISABLED:
+ return SStatus::DISABLED;
+ case hardware::ICameraService::ERROR_PERMISSION_DENIED:
+ return SStatus::PERMISSION_DENIED;
+ case hardware::ICameraService::ERROR_INVALID_OPERATION:
+ return SStatus::INVALID_OPERATION;
+ default:
+ return SStatus::UNKNOWN_ERROR;
+ }
+}
+
+SCaptureResultExtras convertToAidl(const UCaptureResultExtras &src) {
+ SCaptureResultExtras dst;
+ dst.requestId = src.requestId;
+ dst.burstId = src.burstId;
+ dst.frameNumber = src.frameNumber;
+ dst.partialResultCount = src.partialResultCount;
+ dst.errorStreamId = src.errorStreamId;
+ dst.errorPhysicalCameraId = String8(src.errorPhysicalCameraId).string();
+ return dst;
+}
+
+SErrorCode convertToAidl(int32_t errorCode) {
+ switch(errorCode) {
+ case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED:
+ return SErrorCode::CAMERA_DISCONNECTED;
+ case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE :
+ return SErrorCode::CAMERA_DEVICE;
+ case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_SERVICE:
+ return SErrorCode::CAMERA_SERVICE;
+ case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST:
+ return SErrorCode::CAMERA_REQUEST;
+ case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT:
+ return SErrorCode::CAMERA_RESULT;
+ case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER:
+ return SErrorCode::CAMERA_BUFFER;
+ case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISABLED:
+ return SErrorCode::CAMERA_DISABLED;
+ case camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR:
+ return SErrorCode::CAMERA_INVALID_ERROR;
+ default:
+ return SErrorCode::CAMERA_UNKNOWN_ERROR;
+ }
+}
+
+std::vector<SPhysicalCaptureResultInfo> convertToAidl(
+ const std::vector<UPhysicalCaptureResultInfo>& src,
+ std::shared_ptr<CaptureResultMetadataQueue>& fmq) {
+ std::vector<SPhysicalCaptureResultInfo> dst;
+ dst.resize(src.size());
+ size_t i = 0;
+ for (auto &physicalCaptureResultInfo : src) {
+ dst[i++] = convertToAidl(physicalCaptureResultInfo, fmq);
+ }
+ return dst;
+}
+
+SPhysicalCaptureResultInfo convertToAidl(const UPhysicalCaptureResultInfo & src,
+ std::shared_ptr<CaptureResultMetadataQueue> & fmq) {
+ SPhysicalCaptureResultInfo dst;
+ dst.physicalCameraId = String8(src.mPhysicalCameraId).string();
+
+ const camera_metadata_t *rawMetadata = src.mPhysicalCameraMetadata.getAndLock();
+ // Try using fmq at first.
+ size_t metadata_size = get_camera_metadata_size(rawMetadata);
+ if ((metadata_size > 0) && (fmq->availableToWrite() > 0)) {
+ if (fmq->write((int8_t *)rawMetadata, metadata_size)) {
+ dst.physicalCameraMetadata.set<SCaptureMetadataInfo::fmqMetadataSize>(metadata_size);
+ } else {
+ ALOGW("%s Couldn't use fmq, falling back to hwbinder", __FUNCTION__);
+ SCameraMetadata metadata;
+ cloneToAidl(rawMetadata, &metadata);
+ dst.physicalCameraMetadata.set<SCaptureMetadataInfo::metadata>(std::move(metadata));
+ }
+ }
+ src.mPhysicalCameraMetadata.unlock(rawMetadata);
+ return dst;
+}
+
+void convertToAidl(const std::vector<hardware::CameraStatus> &src,
+ std::vector<SCameraStatusAndId>* dst) {
+ dst->resize(src.size());
+ size_t i = 0;
+ for (const auto &statusAndId : src) {
+ auto &a = (*dst)[i++];
+ a.cameraId = statusAndId.cameraId.c_str();
+ a.deviceStatus = convertCameraStatusToAidl(statusAndId.status);
+ size_t numUnvailPhysicalCameras = statusAndId.unavailablePhysicalIds.size();
+ a.unavailPhysicalCameraIds.resize(numUnvailPhysicalCameras);
+ for (size_t j = 0; j < numUnvailPhysicalCameras; j++) {
+ a.unavailPhysicalCameraIds[j] = statusAndId.unavailablePhysicalIds[j].c_str();
+ }
+ }
+}
+
+SCameraDeviceStatus convertCameraStatusToAidl(int32_t src) {
+ SCameraDeviceStatus deviceStatus = SCameraDeviceStatus::STATUS_UNKNOWN;
+ switch(src) {
+ case hardware::ICameraServiceListener::STATUS_NOT_PRESENT:
+ deviceStatus = SCameraDeviceStatus::STATUS_NOT_PRESENT;
+ break;
+ case hardware::ICameraServiceListener::STATUS_PRESENT:
+ deviceStatus = SCameraDeviceStatus::STATUS_PRESENT;
+ break;
+ case hardware::ICameraServiceListener::STATUS_ENUMERATING:
+ deviceStatus = SCameraDeviceStatus::STATUS_ENUMERATING;
+ break;
+ case hardware::ICameraServiceListener::STATUS_NOT_AVAILABLE:
+ deviceStatus = SCameraDeviceStatus::STATUS_NOT_AVAILABLE;
+ break;
+ default:
+ break;
+ }
+ return deviceStatus;
+}
+
+bool areBindersEqual(const ndk::SpAIBinder& b1, const ndk::SpAIBinder& b2) {
+ return !AIBinder_lt(b1.get(), b2.get()) && !AIBinder_lt(b2.get(), b1.get());
+}
+
+status_t filterVndkKeys(int vndkVersion, CameraMetadata &metadata, bool isStatic) {
+ if (vndkVersion == __ANDROID_API_FUTURE__) {
+ // VNDK version in ro.vndk.version is a version code-name that
+ // corresponds to the current version.
+ return OK;
+ }
+ const auto &apiLevelToKeys =
+ isStatic ? static_api_level_to_keys : dynamic_api_level_to_keys;
+ // Find the vndk versions above the given vndk version. All the vndk
+ // versions above the given one, need to have their keys filtered from the
+ // metadata in order to avoid metadata invalidation.
+ auto it = apiLevelToKeys.upper_bound(vndkVersion);
+ while (it != apiLevelToKeys.end()) {
+ for (const auto &key : it->second) {
+ status_t res = metadata.erase(key);
+ if (res != OK) {
+ ALOGE("%s metadata key %d could not be erased", __FUNCTION__, key);
+ return res;
+ }
+ }
+ it++;
+ }
+ return OK;
+}
+
+} // namespace android::hardware::cameraservice::utils::conversion::aidl
\ No newline at end of file
diff --git a/services/camera/libcameraservice/aidl/AidlUtils.h b/services/camera/libcameraservice/aidl/AidlUtils.h
new file mode 100644
index 0000000..c89d7ff
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/AidlUtils.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLUTILS_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLUTILS_H_
+
+#include <aidl/android/frameworks/cameraservice/common/Status.h>
+#include <aidl/android/frameworks/cameraservice/device/CameraMetadata.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureResultExtras.h>
+#include <aidl/android/frameworks/cameraservice/device/ErrorCode.h>
+#include <aidl/android/frameworks/cameraservice/device/CaptureMetadataInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/OutputConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/PhysicalCaptureResultInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/SessionConfiguration.h>
+#include <aidl/android/frameworks/cameraservice/device/StreamConfigurationMode.h>
+#include <aidl/android/frameworks/cameraservice/device/SubmitInfo.h>
+#include <aidl/android/frameworks/cameraservice/device/TemplateId.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraDeviceStatus.h>
+#include <aidl/android/frameworks/cameraservice/service/CameraStatusAndId.h>
+#include <android/hardware/ICameraService.h>
+#include <android/hardware/camera2/ICameraDeviceUser.h>
+#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
+#include <camera/CameraMetadata.h>
+#include <fmq/AidlMessageQueue.h>
+#include <hardware/camera.h>
+
+namespace android::hardware::cameraservice::utils::conversion::aidl {
+
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::CameraMetadata;
+using CaptureResultMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
+
+// VNDK classes
+using SCameraDeviceStatus = ::aidl::android::frameworks::cameraservice::service::CameraDeviceStatus;
+using SCameraMetadata = ::aidl::android::frameworks::cameraservice::device::CameraMetadata;
+using SCameraStatusAndId = ::aidl::android::frameworks::cameraservice::service::CameraStatusAndId;
+using SCaptureResultExtras =
+ ::aidl::android::frameworks::cameraservice::device::CaptureResultExtras;
+using SErrorCode = ::aidl::android::frameworks::cameraservice::device::ErrorCode;
+using SCaptureMetadataInfo = ::aidl::android::frameworks::cameraservice::device::CaptureMetadataInfo;
+using SOutputConfiguration =
+ ::aidl::android::frameworks::cameraservice::device::OutputConfiguration;
+using SPhysicalCaptureResultInfo =
+ ::aidl::android::frameworks::cameraservice::device::PhysicalCaptureResultInfo;
+using SSessionConfiguration =
+ ::aidl::android::frameworks::cameraservice::device::SessionConfiguration;
+using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
+using SStreamConfigurationMode =
+ ::aidl::android::frameworks::cameraservice::device::StreamConfigurationMode;
+using SSubmitInfo = ::aidl::android::frameworks::cameraservice::device::SubmitInfo;
+using STemplateId = ::aidl::android::frameworks::cameraservice::device::TemplateId;
+// NDK classes
+using UCaptureResultExtras = ::android::hardware::camera2::impl::CaptureResultExtras;
+using UOutputConfiguration = ::android::hardware::camera2::params::OutputConfiguration;
+using UPhysicalCaptureResultInfo = ::android::hardware::camera2::impl::PhysicalCaptureResultInfo;
+using USessionConfiguration = ::android::hardware::camera2::params::SessionConfiguration;
+
+// Common macro to log errors returned from stable AIDL calls
+#define LOG_STATUS_ERROR_IF_NOT_OK(status, callName) \
+ if (!(status).isOk()) { \
+ if ((status).getExceptionCode() == EX_SERVICE_SPECIFIC) { \
+ SStatus errStatus = static_cast<SStatus>((status).getServiceSpecificError()); \
+ ALOGE("%s: %s callback failed: %s", __FUNCTION__, callName, \
+ toString(errStatus).c_str()); \
+ } else { \
+ ALOGE("%s: Transaction failed during %s: %d", __FUNCTION__, callName, \
+ (status).getExceptionCode()); \
+ } \
+ }
+
+// Note: existing data in dst will be gone. Caller still owns the memory of src
+void cloneToAidl(const camera_metadata_t *src, SCameraMetadata* dst);
+
+bool cloneFromAidl(const SCameraMetadata &src, CameraMetadata *dst);
+
+int32_t convertFromAidl(SStreamConfigurationMode streamConfigurationMode);
+
+UOutputConfiguration convertFromAidl(const SOutputConfiguration &src);
+
+USessionConfiguration convertFromAidl(const SSessionConfiguration &src);
+
+int convertFromAidl(SOutputConfiguration::Rotation rotation);
+
+int32_t convertFromAidl(STemplateId templateId);
+
+void convertToAidl(const hardware::camera2::utils::SubmitInfo &submitInfo,
+ SSubmitInfo *hSubmitInfo);
+
+SStatus convertToAidl(const binder::Status &status);
+
+SCaptureResultExtras convertToAidl(const UCaptureResultExtras &captureResultExtras);
+
+SErrorCode convertToAidl(int32_t errorCode);
+
+std::vector<SPhysicalCaptureResultInfo> convertToAidl(
+ const std::vector<UPhysicalCaptureResultInfo>& src,
+ std::shared_ptr<CaptureResultMetadataQueue>& fmq);
+
+SPhysicalCaptureResultInfo convertToAidl(const UPhysicalCaptureResultInfo& src,
+ std::shared_ptr<CaptureResultMetadataQueue>& fmq);
+
+void convertToAidl(const std::vector<hardware::CameraStatus> &src,
+ std::vector<SCameraStatusAndId>* dst);
+
+SCameraDeviceStatus convertCameraStatusToAidl(int32_t src);
+
+bool areBindersEqual(const ndk::SpAIBinder& b1, const ndk::SpAIBinder& b2);
+
+status_t filterVndkKeys(int vndkVersion, CameraMetadata &metadata, bool isStatic = true);
+
+} // namespace android::hardware::cameraservice::utils::conversion::aidl
+
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_AIDLUTILS_H_
diff --git a/services/camera/libcameraservice/aidl/DeathPipe.cpp b/services/camera/libcameraservice/aidl/DeathPipe.cpp
new file mode 100644
index 0000000..de46411
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/DeathPipe.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 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 "DeathPipe"
+
+#include "DeathPipe.h"
+
+namespace android::frameworks::cameraservice::utils {
+
+DeathPipe::DeathPipe(IBinder* parent, const ::ndk::SpAIBinder& binder):
+ mParent(parent), mAIBinder(binder) {
+ mDeathRecipient = ::ndk::ScopedAIBinder_DeathRecipient(
+ AIBinder_DeathRecipient_new(DeathPipe::onDeathCallback));
+ // Set an unlinked callback that allows Obituaries to be deallocated
+ AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
+ DeathPipe::onUnlinkedCallback);
+}
+
+status_t DeathPipe::linkToDeath(const sp<IBinder::DeathRecipient>& recipient,
+ void* cookie, uint32_t flags) {
+ LOG_ALWAYS_FATAL_IF(recipient == nullptr, "%s: recipient must be non-nullptr", __FUNCTION__);
+ std::lock_guard<std::mutex> _l(mLock);
+
+ // Create and immortalize an obituary before linking it to death.
+ // The created Obituary can now only be garbage collected if it is unlinked from death
+ std::shared_ptr<Obituary> obituary = std::make_shared<Obituary>(recipient, cookie,
+ flags, /* who= */ mParent);
+ obituary->immortalize();
+
+ // Ensure that "cookie" is a pointer to an immortal obituary.
+ // AIBinder_linkToDeath calls DeathPipe::onUnlinkedCallback if linking to death fails, marking
+ // it for garbage collection
+ binder_status_t ret = AIBinder_linkToDeath(mAIBinder.get(),
+ mDeathRecipient.get(),
+ /* cookie= */ obituary.get());
+ if (ret != STATUS_OK) {
+ return DEAD_OBJECT;
+ }
+ mObituaries.emplace_back(obituary);
+ return NO_ERROR;
+}
+
+status_t DeathPipe::unlinkToDeath(const wp<IBinder::DeathRecipient>& recipient,
+ void* cookie, uint32_t flags,
+ wp<IBinder::DeathRecipient>* outRecipient) {
+ std::lock_guard<std::mutex> _l(mLock);
+ // Temporary Obituary for checking equality
+ std::shared_ptr<Obituary> inObituary = std::make_shared<Obituary>(recipient, cookie,
+ flags, mParent);
+ for (auto it = mObituaries.begin(); it != mObituaries.end(); it++) {
+ if ((*inObituary) == (**it)) {
+ if (outRecipient != nullptr) {
+ *outRecipient = (*it)->recipient;
+ }
+ // Unlink the found Obituary from death. AIBinder_unlinkToDeath calls
+ // DeathPipe::onUnlinkedCallback with the given cookie when unlinking is done
+ binder_status_t ret = AIBinder_unlinkToDeath(mAIBinder.get(),
+ mDeathRecipient.get(),
+ /* cookie= */ (*it).get());
+ mObituaries.erase(it);
+ return ret == STATUS_OK ? NO_ERROR : DEAD_OBJECT;
+ }
+ }
+ return NAME_NOT_FOUND;
+}
+
+DeathPipe::~DeathPipe() = default;
+
+
+void DeathPipe::onDeathCallback(void* cookie) {
+ // Cookie will always be a pointer to a valid immortal Obituary
+ Obituary* obituary = static_cast<Obituary*>(cookie);
+ obituary->onDeath();
+ // Don't call Obituary::clear() because VNDK Binder will call DeathPipe::onUnlinkedCallback()
+ // when it is ready
+}
+
+void DeathPipe::onUnlinkedCallback(void* cookie) {
+ // Cookie will always be a pointer to a valid immortal Obituary.
+ Obituary* obituary = static_cast<Obituary*>(cookie);
+ // Mark obituary to be garbage collected if needed. onDeathCallback won't be called with
+ // this particular cookie after this.
+ obituary->clear();
+}
+
+} // namespace android::frameworks::cameraservice::utils
\ No newline at end of file
diff --git a/services/camera/libcameraservice/aidl/DeathPipe.h b/services/camera/libcameraservice/aidl/DeathPipe.h
new file mode 100644
index 0000000..a816dd0
--- /dev/null
+++ b/services/camera/libcameraservice/aidl/DeathPipe.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 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 FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_DEATHPIPE_H_
+#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_DEATHPIPE_H_
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder.h>
+#include <binder/Parcel.h>
+#include <list>
+
+namespace android::frameworks::cameraservice::utils {
+
+/**
+ * This is a helper class to pipe death notifications from VNDK {@code AIBinder} to
+ * S/NDK {@code IBinder}.
+ *
+ * To use this class, create a DeathPipe member object as a field of NDK interface
+ * implementation, and forward functions {@code BBinder::linkToDeath} and
+ * {@code BBinder::unlinkToDeath} to corresponding DeathPipe functions.
+ */
+class DeathPipe {
+ public:
+ /**
+ * @param parent the NDK Binder object. Assumed to live longer than the DeathPipe
+ * object
+ * @param binder the VNDK Binder object which DeathPipe with subscribe to.
+ */
+ explicit DeathPipe(IBinder* parent, const ::ndk::SpAIBinder& binder);
+ ~DeathPipe();
+
+ status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient, void* cookie,
+ uint32_t flags);
+ status_t unlinkToDeath(const wp<IBinder::DeathRecipient>& recipient,
+ void* cookie, uint32_t flags, wp<IBinder::DeathRecipient>* outRecipient);
+
+ // Static functions that will be called by VNDK binder upon death or unlinking
+ static void onDeathCallback(void* cookie);
+ static void onUnlinkedCallback(void* cookie);
+
+ private:
+ /**
+ * {@code Obituary} is a tiny container that contains some metadata to pass VNDK binder's
+ * death notification to the NDK binder. A pointer to the Obituary is used as the
+ * {@code cookie} in VNDK binder's death notification.
+ *
+ * Theoretically, the VNDK binder might send out death notification after the DeathPipe
+ * object is destroyed, so care must be taken to ensure that Obituaries aren't accidentally
+ * destroyed before VNDK binder stops using its cookies.
+ *
+ */
+ struct Obituary: public std::enable_shared_from_this<Obituary> {
+ wp<IBinder::DeathRecipient> recipient; // NDK death recipient
+ void *cookie; // cookie sent by the NDK recipient
+ uint32_t flags; // flags sent by the NDK recipient
+ wp<IBinder> who; // NDK binder whose death 'recipient' subscribed to
+
+ // Self ptr to ensure we don't destroy this obituary while it can still be notified by the
+ // VNDK Binder. When populated with Obituary::immortalize, this Obituary won't be
+ // garbage collected until Obituary::clear is called.
+ std::shared_ptr<Obituary> mSelfPtr;
+
+ Obituary(const wp<IBinder::DeathRecipient>& recipient, void* cookie,
+ uint32_t flags, IBinder* who) :
+ recipient(recipient), cookie(cookie), flags(flags),
+ who(who), mSelfPtr(nullptr) {}
+
+ // Function to be called when the VNDK Binder dies. Pipes the notification to the relevant
+ // NDK recipient if it still exists
+ void onDeath() const {
+ sp<IBinder::DeathRecipient> r = recipient.promote();
+ if (r == nullptr) { return; }
+ r->binderDied(who);
+ };
+
+ // Should be called before calling AIBinder_linkToDeath. Once this function returns this
+ // Obituary won't be garbage collected until Obituary::clear is called.
+ void immortalize() {
+ mSelfPtr = shared_from_this();
+ }
+
+ // Should be called when this Obituary can be garbage collected.
+ // Typically, after the Obituary is no longer linked to a VNDK DeathRecipient
+ void clear() {
+ mSelfPtr = nullptr;
+ }
+
+ bool operator==(const Obituary& rhs) const {
+ return recipient == rhs.recipient &&
+ cookie == rhs.cookie &&
+ flags == rhs.flags &&
+ who == rhs.who;
+ }
+ };
+
+ // Parent to which the cameraservice wants to subscribe to for death notification
+ IBinder* mParent;
+
+ // VNDK Binder object to which the death notification will be bound to. If it dies,
+ // cameraservice will be notified as if mParent died.
+ ::ndk::SpAIBinder mAIBinder;
+
+ // Owning VNDK's deathRecipient ensures that all linked death notifications are cleaned up
+ // when this class destructs.
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
+ // Lock to protect access to fields below.
+ std::mutex mLock;
+ // List of all obituaries created by DeathPipe, used to unlink death subscription
+ std::list<std::shared_ptr<Obituary>> mObituaries;
+
+};
+
+} // namespace android::frameworks::cameraservice::utils
+
+#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_DEATHPIPE_H_
diff --git a/services/camera/libcameraservice/hidl/VndkVersionMetadataTags.h b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
similarity index 98%
rename from services/camera/libcameraservice/hidl/VndkVersionMetadataTags.h
rename to services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
index 9098fe8..48c804d 100644
--- a/services/camera/libcameraservice/hidl/VndkVersionMetadataTags.h
+++ b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
@@ -21,7 +21,7 @@
* ! Do not edit this file directly !
*
* Generated automatically from vndk_camera_metadata_tags.mako. To be included in libcameraservice
- * only by hidl/Utils.cpp.
+ * only by aidl/AidlUtils.cpp.
*/
/**
@@ -108,5 +108,6 @@
ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER,
ANDROID_EXTENSION_CURRENT_TYPE,
ANDROID_EXTENSION_STRENGTH,
+ ANDROID_SCALER_RAW_CROP_REGION,
} },
};
diff --git a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
index 3392db1..de51ffa 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
+++ b/services/camera/libcameraservice/hidl/AidlCameraDeviceCallbacks.cpp
@@ -17,6 +17,7 @@
#include <hidl/AidlCameraDeviceCallbacks.h>
#include <hidl/Utils.h>
+#include <aidl/AidlUtils.h>
namespace android {
namespace frameworks {
@@ -144,7 +145,7 @@
// Convert Metadata into HCameraMetadata;
FmqSizeOrMetadata hResult;
- using hardware::cameraservice::utils::conversion::filterVndkKeys;
+ using hardware::cameraservice::utils::conversion::aidl::filterVndkKeys;
if (filterVndkKeys(mVndkVersion, result, /*isStatic*/false) != OK) {
ALOGE("%s: filtering vndk keys from result failed, not sending onResultReceived callback",
__FUNCTION__);
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 259e8a5..1d5213d 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -21,6 +21,7 @@
#include <hidl/HidlCameraService.h>
#include <hidl/HidlCameraDeviceUser.h>
#include <hidl/Utils.h>
+#include <aidl/AidlUtils.h>
#include <hidl/HidlTransportSupport.h>
@@ -34,9 +35,9 @@
using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService;
using hardware::hidl_vec;
using hardware::cameraservice::utils::conversion::convertToHidl;
-using hardware::cameraservice::utils::conversion::filterVndkKeys;
using hardware::cameraservice::utils::conversion::B2HStatus;
using hardware::Void;
+using hardware::cameraservice::utils::conversion::aidl::filterVndkKeys;
using device::V2_0::implementation::H2BCameraDeviceCallbacks;
using device::V2_1::implementation::HidlCameraDeviceUser;
diff --git a/services/camera/libcameraservice/hidl/Utils.cpp b/services/camera/libcameraservice/hidl/Utils.cpp
index 057a6e9..2a24a23 100644
--- a/services/camera/libcameraservice/hidl/Utils.cpp
+++ b/services/camera/libcameraservice/hidl/Utils.cpp
@@ -15,7 +15,6 @@
*/
#include <hidl/Utils.h>
-#include <hidl/VndkVersionMetadataTags.h>
#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
#include <cutils/native_handle.h>
#include <mediautils/AImageReaderUtils.h>
@@ -298,31 +297,6 @@
return hPhysicalCaptureResultInfos;
}
-status_t filterVndkKeys(int vndkVersion, CameraMetadata &metadata, bool isStatic) {
- if (vndkVersion == __ANDROID_API_FUTURE__) {
- // VNDK version in ro.vndk.version is a version code-name that
- // corresponds to the current version.
- return OK;
- }
- const auto &apiLevelToKeys =
- isStatic ? static_api_level_to_keys : dynamic_api_level_to_keys;
- // Find the vndk versions above the given vndk version. All the vndk
- // versions above the given one, need to have their keys filtered from the
- // metadata in order to avoid metadata invalidation.
- auto it = apiLevelToKeys.upper_bound(vndkVersion);
- while (it != apiLevelToKeys.end()) {
- for (const auto &key : it->second) {
- status_t res = metadata.erase(key);
- if (res != OK) {
- ALOGE("%s metadata key %d could not be erased", __FUNCTION__, key);
- return res;
- }
- }
- it++;
- }
- return OK;
-}
-
} //conversion
} // utils
} //cameraservice
diff --git a/services/camera/libcameraservice/hidl/Utils.h b/services/camera/libcameraservice/hidl/Utils.h
index e6d4393..ec06571 100644
--- a/services/camera/libcameraservice/hidl/Utils.h
+++ b/services/camera/libcameraservice/hidl/Utils.h
@@ -97,8 +97,6 @@
HStatus B2HStatus(const binder::Status &bStatus);
-status_t filterVndkKeys(int vndk_version, CameraMetadata &metadata, bool isStatic = true);
-
} // conversion
} // utils
} // cameraservice